异步操做git
程序里面全部的任务,能够分红两类:同步任务(synchronous)和异步任务(asynchronous)github
JavaScript 运行时,除了一个正在运行的主线程,引擎还提供一个任务队列(task queue),编程
里面是各类须要当前程序处理的异步任务。(实际上,根据异步任务的类型,存在多个任务队列。为了方便理解,这里假设只存在一个队列。)数组
f1
和f2
,编程的意图是f2
必须等到f1
执行完成,才能执行
function f1() { // ... } function f2() { // ... } f1(); f2();
上面代码的问题在于,若是f1
是异步操做,f2
会当即执行,不会等到f1
结束再执行浏览器
f1
,把f2
写成f1
的回调函数
function f1(callback) { // ... callback(); } function f2() { // ... } f1(f2);
f1.on('done', f2); // 当 f1 发生 done 事件,就执行 f2
对f1
进行改写:服务器
function f1() { setTimeout(function () { // ... f1.trigger('done'); // 表示,执行完成后,当即触发 事件,从而开始执行 }, 1000); }donef2
jQuery.subscribe('done', f2);
function f1() { setTimeout(function () { // ... jQuery.publish('done'); }, 1000); }
f1 执行完成后,向信号中心 jQuery 发布 done 信号,从而引起 f2 的执行网络
jQuery.unsubscribe('done', f2);
var items = [ 1, 2, 3, 4, 5, 6 ]; var results = []; function async(arg, callback) { console.log('参数为 ' + arg +' , 1秒后返回结果'); setTimeout(function () { callback(arg * 2); }, 1000); } function final(value) { console.log('完成: ', value); } function series(item) { if(item) { async( item, function(result) { results.push(result); return series(items.shift()); }); } else { return final(results[results.length - 1]); } } series(items.shift());
var items = [ 1, 2, 3, 4, 5, 6 ]; var results = []; function async(arg, callback) { console.log('参数为 ' + arg +' , 1秒后返回结果'); setTimeout(function () { callback(arg * 2); }, 1000); } function final(value) { console.log('完成: ', value); } items.forEach(function(item) { async(item, function(result){ results.push(result); if(results.length === items.length) { final(results[results.length - 1]); } }) });
forEach
方法会同时发起六个异步任务,等到它们所有完成之后,才会执行 final
函数
n
个异步任务,这样就避免了过度占用系统资源。
var items = [ 1, 2, 3, 4, 5, 6 ]; var results = []; var running = 0; var limit = 2; function async(arg, callback) { console.log('参数为 ' + arg +' , 1秒后返回结果'); setTimeout(function () { callback(arg * 2); }, 1000); } function final(value) { console.log('完成: ', value); } function launcher() { while(running < limit && items.length > 0) { var item = items.shift(); async(item, function(result) { results.push(result); running--; if(items.length > 0) { launcher(); } else if(running == 0) { final(results); } }); running++; } } launcher();
上面代码中,最多只能同时运行两个异步任务。变量 running 记录当前正在运行的任务数,只要低于门槛值,就再启动一个新的任务,若是等于 0,就表示全部任务都执行完了,这时就执行 final() 函数。多线程