Home  >  Article  >  Web Front-end  >  A Beginner’s Guide to Asynchronous Programming in JavaScript

A Beginner’s Guide to Asynchronous Programming in JavaScript

伊谢尔伦
伊谢尔伦Original
2017-06-16 09:59:201098browse

Single thread of JavaScript

When a single thread executes a program, the program paths it takes are arranged in consecutive order. The first ones must be processed, and the last ones must be processed. will be executed. Only specific code can be executed at a specific time, and other code will be blocked.

Single Thread is an infatuated young man who is single-minded and devoted. Single-threaded means that the process has only one thread; multi-threaded means that the process has multiple threads.

Based on JavaScript's single-threaded language execution environment and its shortcomings, JavaScript's synchronous and asynchronous programming methods are proposed.

Synchronous, that is, the task is executed step by step, and the subsequent code can be executed only after the current code is executed; asynchronously, there is no need to wait after starting to execute the current code, and the subsequent tasks can be continued. After the current task is executed, you can Notify callers through status, notifications, and callbacks.

A Beginner’s Guide to Asynchronous Programming in JavaScript

Asynchronous Programming in JavaScript

The JavaScript language execution environment is single-threaded. When a single-thread executes a program, the program paths it takes are arranged in consecutive order. The first ones must be processed before the later ones are executed. Only specific code can be executed at a specific time and will block other codes. Asynchronous programming can make up for its shortcomings. In this article, we explain JavaScript asynchronous programming.

JavaScript asynchronous programming implementation

JavaScript asynchronous programming implementation mainly falls into three categories: callback functions, publish and subscribe, and Promise objects.

Callback function

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
···

All print out 5. To understand why, you need to understand three points:

i here is the variable of the context environment where the for loop is located, and There is only one i;

i==5 at the end of the loop;

The JavaScript single-threaded event handler will not execute the next event until the thread is idle.

You may have seen code similar to this:

·

··
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异步编程入门的全部内容了,感谢大家的阅读!

The above is the detailed content of A Beginner’s Guide to Asynchronous Programming in JavaScript. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn