js语言的执行环境是"单线程":一次只能完成一件任务,如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推。
这种模式的好处是实现起来比较简单,执行环境相对单纯;坏处是只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行。常见的浏览器无响应(假死),往往就是因为某一段Javascript代码长时间运行(比如死循环),导致整个页面卡在这个地方,其他任务无法执行。
为了解决这个问题,Javascript语言将任务的执行模式分成两种:同步(Synchronous)和异步(Asynchronous)。
"同步模式"就是上一段的模式,后一个任务等待前一个任务结束,然后再执行,程序的执行顺序与任务的排列顺序是一致的、同步的;"异步模式"则完全不同,每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。
一、回调函数
function f2(){ console.log("f2") // f2的代码 } function f1(callback){ console.log("f1"); // f1的代码 setTimeout(function(){ callback(); }, 1000); } > f1(f2) f1 f2
同步变异步,f1不会阻塞f2。简单; 高度耦合,每个任务只能指定一个回调函数,无法return/try/catch/throw。
二、事件监听
function f2(){ console.log("f2") // f2的代码 }
f1.on('done', f2); // 事件绑定 function f1(callback){ console.log("f1"); // f1的代码 setTimeout(function(){ f1.trigger('done'); }, 1000); } > f1(f2) f1 f2
事件驱动,可绑定多个,去耦合。
三、发布订阅
function f2(){ console.log("f2") // f2的代码 }
jQuery.subscribe('done', f2); // 订阅信号 function f1(callback){ console.log("f1"); // f1的代码 setTimeout(function(){ jQuery.publish('done'); // 发布信号 }, 1000); } > f1(f2) f1 f2
类似事件监听,优于上者。
=== es6 ===
四、Promise
Promises对象是CommonJS工作组提出的一种规范
Promise是一个构造函数,方法有:all、reject、resolve、then、catch
resolve:成功
reject:失败
(复制到控制台查看运行结果)
function runAsync1(){ var p = new Promise(function(resolve, reject){ // 做一些异步操作 setTimeout(function(){ console.log('异步任务1执行完成'); resolve('随便什么数据1'); }, 1000); }); return p; } function runAsync2(){ var p = new Promise(function(resolve, reject){ // 做一些异步操作 setTimeout(function(){ console.log('异步任务2执行完成'); resolve('随便什么数据2'); }, 2000); }); return p; } function runAsync3(){ var p = new Promise(function(resolve, reject){ // 做一些异步操作 setTimeout(function(){ console.log('异步任务3执行完成'); resolve('随便什么数据3'); }, 2000); }); return p; } runAsync1() .then(function(data){ console.log(data); return runAsync2(); }) .then(function(data){ console.log(data); return '直接返回数据'; // 这里直接返回数据 }) .then(function(data){ console.log(data); });
all:并行执行,谁跑得慢,以谁为准进行回掉
Promise .all([runAsync1(), runAsync2(), runAsync3()]) // 并行 .then(function(results){ console.log(results); });
race:并行执行,谁跑得快,以谁为准进行回掉
Promise .race([runAsync1(), runAsync2(), runAsync3()]) .then(function(results){ console.log(results); });
function getNumber(){ var p = new Promise(function(resolve, reject){ // 做一些异步操作 setTimeout(function(){ var num = Math.ceil(Math.random()*10); // 生成1-10的随机数 if(num <= 5){ resolve(num); // 成功,获取数字 } else{ reject('数字太大了'); //失败,传递参数 } }, 2000); }); return p; } getNumber() .then( function(data){ // 成功 console.log('resolved'); console.log(data); }, function(reason, data){ // 失败 console.log('rejected'); console.log(reason); } );
// 这个和上面功能一样,但是上面有异常不会卡死 getNumber() .then(function(data){ console.log('resolved'); console.log(data); }) .catch(function(reason){ console.log('rejected'); console.log(reason); });
五、generator
=== es7 ===
六、async/await
async-await
是promise
和generator
的语法糖
参考资料
https://www.cnblogs.com/whybxy/p/7645578.html
https://www.cnblogs.com/chenshufang/p/9927536.html
https://segmentfault.com/a/1190000011526612?utm_source=tag-newest
http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html?bsh_bid=1736591883
未完待续。。。