Maison  >  Article  >  interface Web  >  Guide du débutant sur la programmation asynchrone en JavaScript

Guide du débutant sur la programmation asynchrone en JavaScript

伊谢尔伦
伊谢尔伦original
2017-06-16 09:59:201099parcourir

Thread unique de JavaScript

Lorsqu'un seul thread exécute un programme, les chemins du programme qu'il emprunte sont classés dans un ordre consécutif. Les premiers doivent être traités. , et les derniers doivent être traités seront exécutés. Seul un code spécifique peut être exécuté à un moment précis et les autres codes seront bloqués.

Single Thread est un garçon passionné, déterminé et dévoué. Monothread signifie que le processus n'a qu'un seul thread ; multithread signifie que le processus a plusieurs threads.

Basées sur l'environnement d'exécution du langage monothread de JavaScript et ses lacunes, les méthodes de programmation synchrone et asynchrone de JavaScript sont proposées.

Synchrone, c'est-à-dire que la tâche est exécutée étape par étape et que le code suivant ne peut être exécuté qu'après l'exécution asynchrone du code actuel, il n'est pas nécessaire d'attendre après le démarrage pour exécuter le code actuel ; et les tâches suivantes peuvent être poursuivies. Une fois la tâche en cours exécutée, vous pouvez avertir les appelants via l'état, les notifications et les rappels.

Guide du débutant sur la programmation asynchrone en JavaScript

Programmation asynchrone en JavaScript

L'environnement d'exécution du langage JavaScript est monothread. Lorsqu'un seul thread exécute un programme, les chemins du programme qu'il emprunte sont organisés dans un ordre consécutif. Les premiers doivent être traités avant que les suivants ne soient exécutés. Seul un code spécifique peut être exécuté à un moment précis et bloquera d'autres codes. La programmation asynchrone peut compenser ses lacunes. Dans cet article, nous expliquons la programmation asynchrone JavaScript.

Implémentation de la programmation asynchrone JavaScript

L'implémentation de la programmation asynchrone JavaScript est principalement divisée en trois catégories : les fonctions de rappel, la publication et l'abonnement et les objets Promise.

La fonction Callback

function a(fn) {
//a函数任务...
setTimeout(function() {
fn();
}, 0);
console.log('a');
}
function b(fn) {
//b函数任务
console.log('b');
}
a(b);
以上代码打印值顺序如何呢?结果是先a后b。至于为什么,不得不说说setTimeout。再细微的东西,只要存在,我们都能从中弄出些精华,就比如setTimeout。
请看代码:
···
for (var i = 0; i < 5; i ++) {
setTimeout(function(){
console.log(i);
}, 0);
}
console.log(i);
//5 ; 5 ; 5 ; 5; 5
···

imprime les 5. Pour comprendre pourquoi, il faut comprendre trois points :

i voici la variable du contexte où se trouve la boucle for est situé, Il y a et il n'y a qu'un seul i;

i==5 à la fin de la boucle;

Le processeur d'événements JavaScript monothread n'exécutera pas l'événement suivant tant que le thread est inactif.

Vous avez peut-être vu un code similaire à celui-ci :

·

··
function f1(callback) {
setTimeout(function() {
f2(functions() {
setTimeout({
callback(...) ;
}, 0);
});
}, 0);
}
function(callback) {//...}
···

请避免这样的多层嵌套回调。

发布订阅

PubSub,即Publish/Subscribe,发布、订阅模式, 用以分发事件。常见的有jQuery的自定义事件监听、Node的EventEmitter对象等。

jQuery事件监听

$(&#39;#btn&#39;).on(&#39;myEvent&#39;, function(e) {
console.log(&#39;There is my Event&#39;);
});
$(&#39;#btn&#39;).trigger(&#39;myEvent&#39;);
PubSub
var PubSub = function(){
this.handlers = {};
};
PubSub.prototype.subscribe = function(eventType, handler) {
if (!(eventType in this.handlers)) {
this.handlers[eventType] = [];
}
this.handlers[eventType].push(handler); //添加事件监听器
return this;//返回上下文环境以实现链式调用
};
PubSub.prototype.publish = function(eventType) {
var _args = Array.prototype.slice.call(arguments, 1);
for (var i = 0, _handlers = this.handlers[eventType]; i < _handlers.length; i++) {
_handlers[i].apply(this, _args);//遍历事件监听器
}
return this;
};
var event = new PubSub;//构造PubSub实例
event.subscribe(&#39;list&#39;, function(msg) {
console.log(msg);
});
event.publish(&#39;list&#39;, {data: [&#39;one,&#39;, &#39;two&#39;]});
//Object {data: Array[2]}

以上代码就是一个简易的订阅发布模式基本实现,还可以对其进行完善,如添加只执行一次事件监听器等。

Promise对象

Promise是CommonJS的规范之一,拥有resolve、reject、done、fail、then等方法,能够帮助我们控制代码的流程。

一个promise可能有三种状态:等待(pending)、已完成(fulfilled)、已拒绝(rejected);

一个promise的状态只可能从“等待”转到“完成”态或者“拒绝”态,不能逆向转换,同时“完成”态和“拒绝”态不能相互转换;

promise必须实现then方法(可以说,then就是promise的核心),而且then必须返回一个promise,同一个promise的then可以调用多次,并且回调的执行顺序跟它们被定义时的顺序一致;

then方法接受两个参数,第一个参数是成功时的回调,在promise由“等待”态转换到“完成”态时调用,另一个是失败时的回调,在promise由“等待”态转换到“拒绝”态时调用。

同时,then可以接受另一个promise传入,也接受一个“类then”的对象或方法,即thenable对象。

* jQuery之Promise
var prom = new $.Deferred();
prom.done(function(value) {
console.log(value + &#39; Done&#39;);
});
prom.fail(function(value) {
console.log(value + &#39; Fail&#39;);
});
prom.always(function(v) {
console.log(&#39; always here&#39;);
});
prom.resolve(&#39;OK&#39;);
Deferred是Promise的超集,相对于Promise只提供then方法添加调用,触发这些调用需要其他支持,使用Deferred实例可直接触发调用。
Promise简单实现
function defer() {
var tasks = [],
progresses = [],
state = &#39;pending&#39;,
value,
reason;
return {
resolve: function(_value) {
if (tasks) {
value = ref(_value);
tasks.forEach(function(task) {
nextTick(function() {
value.then.apply(value, task);
});
});
tasks = null;
state = &#39;resolved&#39;;
}else {
if (state === &#39;resolved&#39;) {
throw new Error(&#39;A promise should been resolved once.&#39;);
}
}
},
reject: function(reason) {
if (tasks) {
value = ref(reason);
tasks.forEach(function(task) {
nextTick(function() {
value.then.apply(value, [task[1], task[0]]);
});
});
tasks = undefined;
state = &#39;rejected&#39;;
}else {
if (state === &#39;rejected&#39;) {
throw new Error(&#39;A promise should been rejected once.&#39;);
}
}
},
notify: function(progress) {
if (state === &#39;resolved&#39; || state === &#39;rejected&#39;) {
return;
}
progresses.push(progress);
},
promise: {
then: function(_callback, _errback, _notifyback) {
var deferred = defer();
_callback = _callback || function(value) {
return value;
};
_errback = _errback || function(reason) {
return reject(reason);
};
_notifyback = _notifyback || function(progress) {
return progress;
};
var callback = function(value) {
var result;
try {
result = _callback(value);
}catch(e) {
deferred.reject(e);
}finally {
deferred.resolve(result);
}
};
var errback = function(reason) {
var result;
try {
result = _errback(reason);
}catch(e) {
deferred.reject(e);
}finally {
deferred.resolve(result);
}
}
nextTick(function() {
while (progresses.length) {
try {
_notifyback(progresses.shift());
}catch(e) {
deferred.reject(e);
break;
}
}
});
if (tasks) {
tasks.push([callback, errback]);
}else {
nextTick(function() {
if (state === &#39;rejected&#39;) {
value.then(errback);
}else if (state === &#39;resolved&#39;) {
value.then(callback);
}
});
}
return deferred.promise;
}
}
};
}
var ref = function(value) {
if (value && typeof value.then === &#39;function&#39;) {
return value;
}
return {
then: function(callback) {
return ref(callback(value));
}
}
};
var reject = function(reason) {
return {
then: function(callback, errback) {
return ref(errback(reason));
}
};
};
var nextTick = function(callback) {
setTimeout(callback, 0);
};
//Promise实例
var deferred = defer(),
promise = deferred.promise;
promise.then(function(value) {
console.log(value);
throw &#39;zhangsan&#39;;
}).then(function (v) {
console.log(v);
}, function (err) {
console.error(err);
done();
});
setTimeout(function () {
deferred.resolve(&#39;zhangsan1&#39;);
}, 1000);

以上就是js异步编程入门的全部内容了,感谢大家的阅读!

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn