Promise & Q
https://github.com/kriskowal/q
传统模式中将方法当做函数的参数,并在运行时执行.
step1(function (value1) {
step2(value1, function(value2) {
step3(value2, function(value3) {
step4(value3, function(value4) {
// Do something with value4
});
});
});
});
显而易见,回调链越长,越不直观.
我们使用 Promise 或 Q 来整理这些回调后代码会变成这样.
Q.fcall(promisedStep1)
.then(promisedStep2)
.then(promisedStep3)
.then(promisedStep4)
.then(function (value4) {
// Do something with value4
})
.catch(function (error) {
// Handle any error from all above steps
})
.done();
Q 和 ES2015 中的原生 Promise 作用基本一样. 都遵循 Promise A+ 规范,只不过 Promise 是原生的,我们可以继续使用 Q 来当 Promise 的 polyfill
let p = new Promise((resolve,reject)=>{
setTimeout(n=>{
resolve(1);
},1000);
}).then(n=>{
return n+1;
}).then(n=>{
return n+2;
});
async.js
http://caolan.github.io/async/
使用 async 来处理回调可以起到相同的作用,但是他的用法不同:
比如我们可以依次执行一连串回调
var async = require("async")
async.series([
function(callback) {
setTimeout(n => {
console.log(1);
callback();
}, 2000);
},
function(callback) {
setTimeout(n => {
console.log(2);
callback();
}, 1000);
}
]);
//=> 1
//=> 2
或者使用 waterfall 来达到传值的目的.
async.waterfall([
function(callback) {
callback(null, 'one', 'two');
},
function(arg1, arg2, callback) {
// arg1 now equals 'one' and arg2 now equals 'two'
callback(null, 'three');
},
function(arg1, callback) {
// arg1 now equals 'three'
callback(null, 'done');
}
], function (err, result) {
// result now equals 'done'
});
如果要 "依次" 拼凑出一连串回调,用 async 可能会比 Promise 方便一些.
Generator
Promise 是 javascript 社区的产物, 而 Generator 是从其它语言借鉴过来的.
Generator 意为"协同器" 可以让多个线程或函数共同完成一个任务.
function* myGen(num){
var num1 = yield num;
console.log(num1);
}
let gem = myGen(1);
let num = gem.next().value;
gem.next(num+1)
yield 关键字后即是要抛出的变量,然后在获取这个变量后,再调用 next() 函数继续.
自动执行的 Generator:
其核心原理是: yield 后抛出一个 Promise 然后在其 then 中执行 next
"use strict";
function* myGen(){
let g1 = yield new Promise((resolve,reject)=>{
setTimeout(n=>{
console.log("1");
resolve(2);
},1000);
});
let g2 = yield new Promise((resolve,reject)=>{
setTimeout(n=>{
console.log(g1);
resolve(g1+1);
},1000);
});
console.log(g2)
}
var gen = myGen();
gen.next().value.then(s=>{
gen.next(s).value.then();
});
当然最后的嵌套还是有点蛋疼,我们可以写一个自动执行器:
var gen = myGen();
function run(gen){
var g = gen();
function next(data){
var result = g.next(data);
if (result.done) return result.value;
result.value.then(function(data){
next(data);
});
}
next();
}
run(myGen);