这篇文章不是为了介绍回调地狱也不是介绍Promise,而是介绍如何实现具有继发关系的多个请求。
何为继发关系?
比如有三个请求A、B、C,B要等待A请求的结果再发起请求,C要等待B请求的结果再发起请求,也就是A - B - C有所关联,这就是继发关系。
问题的转移
一直以来,回调地狱是大问题,随着ES6的完成,Promise出现了,解决了回调地狱,但在请求具有继发关系的请求时,又出现了另一个问题,会出现长链式then。
async/await
现在我们可以使用ES7中的
async函数返回一个 Promise 对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
Async用来定义异步函数
语法:async function someName(){}
Await用来暂停异步函数的执行
语法:
更多关于async函数: es6.ruanyifeng.com/#docs/async
下面直接上例子。
如果支持async,比如
何为继发关系?
比如有三个请求A、B、C,B要等待A请求的结果再发起请求,C要等待B请求的结果再发起请求,也就是A - B - C有所关联,这就是继发关系。
问题的转移
一直以来,回调地狱是大问题,随着ES6的完成,Promise出现了,解决了回调地狱,但在请求具有继发关系的请求时,又出现了另一个问题,会出现长链式then。
async/await
现在我们可以使用ES7中的
async/await了。async函数返回一个 Promise 对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
Async用来定义异步函数
语法:async function someName(){}
Await用来暂停异步函数的执行
语法:
const step = async function someName(){...}更多关于async函数: es6.ruanyifeng.com/#docs/async
下面直接上例子。
如果支持async,比如
Typescript/Node 7.6+中,可以这样快速实现:asyncRequest(requestArrs: any, context: any) {
const values = [];
let num = 0;
const req = async () => {
try {
for (const request of requestArrs) {
values[num] = await context[request](values[num - 1] || null);
num++;
}
return values[values.length - 1];
} catch (err) {
console.error(err);
}
};
return req;
}
const steps = {
step1(res) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(321);
}, 1000);
});
},
step2(res) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(123 + res);
}, 500);
});
}
};
asyncRequest(['step1', 'step2'], steps)().then(res => {
console.log(res);
});
asyncRequest函数的第一个参数是一个字符串数组,包含要执行的函数名称;第二个参数是这些函数的上下文,它返回一个异步函数,也就是上面的req函数,异步函数最终返回的是一个promise,所以你可以使用then。 在Node端如何还未支持async,但要支持ES6,可以借助Generator函数和co库:const co = require('co');
const asyncRequest = function(requestArrs, context) {
const values = [];
let num = 0;
const req = function* () {
try {
for (const request of requestArrs) {
values[num] = yield context[request](values[num - 1] || null);
num++;
}
return values[values.length - 1];
} catch (err) {
console.error(err);
}
};
return req;
}
const steps = {
step1(res) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(321);
}, 1000);
});
},
step2(res) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(123 + res);
}, 500);
});
}
};
const async = asyncRequest(['step1', 'step2'], steps);
co(async).then(res => {
console.log(res)
});
就是这么简单,只需定义多个请求函数,就可以完成继发关系的请求,再也不用多层嵌套或长链式then了。如果有疑问,欢迎在下方评论留言!