我有多个耗时的功能,我希望在完成所有功能后运行一个功能,例如:
data.x = thisTakes2Seconds();
data.y = thisTakes5Seconds();
http.post(data);
我熟悉Javascript中回调的概念,但是如果我有几个函数,我真的应该有几个函数的嵌套回调吗?
答案 0 :(得分:1)
为了轻松处理异步函数,最好的方法是使用promises
和async/await
function thisTakes2Seconds() {
return new Promise(resolve => setTimeout(() => resolve(3), 200)); // 0.2 to avoid waiting :P
}
function thisTakes5Seconds() {
return new Promise(resolve => setTimeout(() => resolve(5), 500));
}
async function foo() {
const data = {};
data.x = await thisTakes2Seconds();
data.y = await thisTakes5Seconds();
// This will run once both promises have been resolved
console.log(data);
}
foo()
.then(() => console.log('done!')
.catch(err => console.error(err));
如果您希望并行执行这两项功能,可以这样做,并等待两者完成Promise.all
async function foo() {
const data = {};
// Promise.all returns an array where each item is the resolved
// value of the promises passed to it, maintaining the order
// So we use destructuring to assign those values
[data.x, data.y] = await Promise.all([
thisTakes2Seconds(),
thisTakes5Seconds()
]);
console.log(data);
}
如果你已经有一个使用回调的异步功能,你可以轻松地将其转换为promises。
function myAsyncFunction(callback) {
setTimeout(() => {
callback(Math.random());
}, 200);
}
function myAsyncFunctionPromise() {
return new Promise((resolve, reject) => {
myAsyncFunction(resolve);
// If there is an error callback, just pass reject too.
});
}
像bluebird这样的库已经有了实用方法来实现回调API。
http://bluebirdjs.com/docs/api/promise.promisify.html
如果您在浏览器上运行它,并且需要支持过时的,您可以使用babel将async/await
转换为ES5
答案 1 :(得分:1)
您的thisTakesXSeconds
函数会立即返回结果。这告诉我们他们是同步的。无需回调,代码只需约7秒即可运行。
如果 thisTakesXSeconds
启动异步进程需要X秒(尽管事实上你返回结果显示否则),我们将研究管理完成过程的方法。
我真的应该嵌套几个函数的回调吗?
这个问题,以及对答案“是”的普遍不满,是我们现在有承诺甚至async
功能的原因。 : - )
如果函数可以并行运行,那么你的thisTakesXSeconds
函数会返回一个承诺,然后沿着这些行做一些事情:
Promise.all([
thisTakes2Seconds(),
thisTakes5Seconds()
])
.then(([x, y]) => {
data.x = x;
data.y = y;
// use or return `data` here
})
// return the promise or add a `catch` handler
如果他们需要连续运行(一个接一个),那么
thisTakes2Seconds()
.then(x => {
data.x = x;
return thisTakes5Seconds();
})
.then(y => {
data.y = y;
// use or return `data` here
})
// return the promise or add a `catch` handler
...在async
函数中看起来更清晰:
data.x = await thisTakes2Seconds();
data.y = await thisTakes5Seconds();
// use or return `data` here
// add appropriate error handling (at this level or when calling the function)
答案 2 :(得分:0)
在执行了几个异步调用后,我用来处理执行某些代码的一种技术是使用“已完成”的计数器或对象。
每个函数都执行包含
的回调if (counter == numberOfFuntionsIWantedToComplete)
doTheAfterWeHaveAllDataThing`