在js里面,偶尔会遇见需要多个异步按照顺序执行请求,又不想多层嵌套,,这里和promise.all的区别在于,promise或者Jquery里面的$.when 是同时发送多个请求,一起返回,发出去的顺序是一起;这里是按照顺序发请求
方法 一 、首先创建一个迭代器,接收任意多个函数参数
function nextRegister(){
var args = arguments;
var count = 0;
var comm = {};
function nextTime(){
count++;
if(count < args.length){
if(args[count] && Object.prototype.toString.call(args[count]) == '[object Function]'){
args[count](comm,nextTime);
}
}
}
if(args[count] && Object.prototype.toString.call(args[count]) == '[object Function]'){
args[count](comm,nextTime);
}
}
创建多个异步的函数,注入到迭代器中
/*
comm:多个函数,公用的变量
next:调用下一个函数
* */
function fn1(comm,next){
console.log('1');
comm.age = 20;
next();
}
function fn2(comm,next){
next();
console.log('2');
console.log(comm.age);
}
function fn3(comm,next){
console.log('3');
}
//开始执行迭代
nextRegister(fn1,fn2,fn3);
在这里,fn1-fn3函数中,做异步操作,知道在异步成功的时候调用next()就可以继续执行下一个函数,同时可以将前面函数返回的结果,绑定在comm上,带到下一个函数中
方法 二、参考express 和 koa 的写法
1、es5写法
function Iterator(){
this.middlewares = [];
}
Iterator.prototype.use = function(fn){
this.middlewares.push(fn);
return this;
}
Iterator.prototype.run = function(ctx){
function createNext(middleware, oldNext) {
return function(){
middleware(ctx, oldNext)
};
}
let len = this.middlewares.length;
let next = function(){};
for (let i = len - 1; i >= 0; i--) {
let currentMiddleware = this.middlewares[i];
next = createNext(currentMiddleware, next); //从后往前遍历,前面的闭包保存后面的 next
}
next();
}
var iterator = new Iterator();
iterator.use(function(ctx,next){
//这里可以做一些异步操作,只需要成功后调用 next
console.log("start:a");
next();
console.log("end:a");
});
iterator.use(function(ctx,next){
console.log("start:b");
next();
console.log("end:b");
});
iterator.run();
2、es6 的 async 写法
class Iterator{
constructor(){
this.middlewares = [];
}
use(fn){
this.middlewares.push(fn); //存入任务
return this;
}
async run(ctx){
function createNext(middleware, oldNext) {
return async () => {
await middleware(ctx, oldNext);
}
}
let len = this.middlewares.length;
let next = async () => {
return Promise.resolve();
};
for (let i = len - 1; i >= 0; i--) {
let currentMiddleware = this.middlewares[i];
next = createNext(currentMiddleware, next);
}
await next();
}
}
let app = new Iterator();
app.use(async (ctx,next)=>{
console.log("start:a");
await next();
console.log("end:a");
});
app.use(async (ctx,next)=>{
console.log("start:b");
await next();
console.log("end:b");
});
app.run();