在浏览器中,JavaScript引擎是单线程执行的。也就是说,在同一时间内,只能有一段代码被JavaScript引擎执行。页面加载时,JavaScript引擎会顺序执行页面上所有JavaScript代码,优先执行同步代码。而异步代码由事件触发引擎按照“事件发生”的顺序添加到JavaScript引擎的任务队列中,待所有同步代码执行结束后,JavaScript引擎会按照任务队列中的顺序来执行异步代码。
也就是说当有多个任务执行时,会按照顺序优先执行同步任务队列,再执行异步任务队列。
setTimeout(function(){ console.log(‘hello world‘); },0);//虽然此处异步任务时间间隔为0,但仍然排在同步队列之后执行 var t = 300000000; for(var i=0;i<=t;i++){//此处进行一次耗时操作 if(i==t){ console.log(t); } }
//结果为
//300000000
//hello world
因此可以利用这一原理,实现简单的链式操作和流程控制:
LazyMan(‘Hank‘).sleepFirst(1).eat(‘breadfast‘).sleep(2).eat(‘lunch‘).sleep(3).eat(‘dinner‘);//结果可以不按照顺序执行
function LazyMan(name) { var queue = []; var task = {//待执行的方法 wait: function (second) { return function () { setTimeout(function () { console.log(‘Wake up after ‘ + second); next(); }, second * 1000); }; }, eat: function (part) { return function () { console.log(‘Eat ‘ + part + ‘~‘); next(); }; }, hi: function () { console.log(‘Hi! This is ‘ + name + ‘!‘); next(); } }; queue.push(task.hi); //这个定时器会在链式操作全部推入queue数组中后(即同步代码执行完毕)才会调用 setTimeout(function () { next(); }, 0);
//每次执行next都会把当前queue队列[fn,.....]的第一个方法shift出来并执行,如果队列为空则链式操作执行完毕。
function next() { var fn = queue.shift(); fn && fn(); }
return {
//链式调用的时候会先把这些调用的一系列任务方法push或unshift到一个quue数组中 sleep: function (second) { queue.push(task.wait(second)); return this; }, sleepFirst: function (second) { queue.unshift(task.wait(second)); return this; }, eat: function (part) { queue.push(task.eat(part)); return this; } }; };
//输出
Wake up after 1
Hi! This is Hank!
Eat breadfast~
Wake up after 2
Eat lunch~
Wake up after 3
Eat dinner~
参考 http://hushicai.com/2015/05/07/a-frontend-interview-question-of-weixin.html
原文:http://www.cnblogs.com/dupd/p/6260957.html