首先,让我们先了解下串并行的定义
串并行指的是任务的执行方式。串行是指多个任务时,各个任务按顺序执行,完成一个之后才能进行下一个。并行指的是多个任务可以同时执行。异步是多个任务并行的前提条件。
并行
首先,我们都知道js在浏览器中是单线程(应该说是主线程,还有诸如异步的event线程,绘制线程,当主线程工作时,其他线程会堵塞),也就是说,只有当事件是异步时,浏览器才有可能实现并行逻辑。
那最常见的并行逻辑自然就是多个异步ajax请求时:
当es6出来后,解决回调地狱的promise,本质上promise是一个裹着串行执行(顺序执行)外衣的一个并行逻辑(当然,并不是说promise不能用来做串行逻辑,而是大部分情况下):
let first = new Promise( (resolve) => {
ajax(url, {}, (data)=>{
resolve(data.result);
})
});
let second = new Promise( (resolve) => {
ajax(url, {}, (data)=>{
resolve(data.result);
})
});
let third = new Promise((resolve)=> {
ajax(url, {}, (data)=>{
resolve(data.result);
})
});
Promise.all([first,second,third]).then((result) => {
console.log(result);
});
当你打开chrome的控制台,查看network后,仍能发现是并行请求;
也就是说promise实际上是先将里面函数执行,保留resolve结果,等到then再把结果传递到下个promise;
依照 promises 规范,一旦一个 promise 被创建,它就被执行了(这是出自一篇文章,详细讲解了promise的设计有兴趣可以了解,http://fex.baidu.com/blog/2015/07/we-have-a-problem-with-promises/)
在js中,并行逻辑一般只会出现在异步ajax请求,在web worker(有兴趣可以去了解)出现后,出现了新的js线程,在主线程外运行。
串行
ok,那如何设计一个串行逻辑呢,如果细心,可以从node.js里面找到答案:
app.use(function(req, res, next) {
......
next(err);
});
想到了吗:用next挂载中间件的方式,将事件顺序传递;
那程序上如何设计呢,编写一个LazyMan吧:
function _LazyMan(name){
this.tasks = [];
var self = this;
var fn = (function(n){
var name = n;
return function(){
console.log("Hi! This is " + name + "!");
self.next();
}
})(name);
this.tasks.push(fn);
setTimeout(function(){
self.next();
},0)
}
_LazyMan.prototype.next = function(){
var fn = this.tasks.shift();
fn && fn();
};
_LazyMan.prototype.eat = function(name){
var self = this;
var fn = (function(name){
return function(){
console.log("Eat " + name + "~");
self.next();
}
})(name);
this.tasks.push(fn);
return this;
};
_LazyMan.prototype.sleep = function(time){
var self = this;
var fn = (function(time){
return function() {
setTimeout(function(){
console.log("Wake up after " + time + "s!");
self.next();
}, time * 1000);
}
})(time);
this.tasks.push(fn);
return this;
};
_LazyMan.prototype.sleepFirst = function(time){
var self = this;
var fn = (function(time){
return function() {
setTimeout(function() {
console.log("Wake up after " + time + "s!");
self.next();
}, time * 1000);
}
})(time);
this.tasks.unshift(fn);
return this;
};
function LazyMan(name){
return new _LazyMan(name);
}
整个过程就是 由函数进来->调用原型链上方法->传入数组->next中转->数组调用
1.使用next作为中间件传递的中转站;
2.链式调用;
作为es6的语法糖来说,promise我们简单知道使用场景和如何使用也就可以了,不过理解串并行思想对理解js的回调,node的event-loop都很有帮助
网友评论