我有多个耗时的函数,我希望在它们全部完成后运行一个函数,例如:
data.x = thisTakes2Seconds();
data.y = thisTakes5Seconds();
http.post(data);
我了解Javascript中回调函数的概念,但如果我有多个函数,我真的需要嵌套多层回调函数吗?
我有多个耗时的函数,我希望在它们全部完成后运行一个函数,例如:
data.x = thisTakes2Seconds();
data.y = thisTakes5Seconds();
http.post(data);
我了解Javascript中回调函数的概念,但如果我有多个函数,我真的需要嵌套多层回调函数吗?
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));
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);
}
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转换为Promise。
http://bluebirdjs.com/docs/api/promise.promisify.html
async/await
转译为ES5。thisTakesXSeconds
函数立即返回它们的结果。这告诉我们它们是同步的。不需要回调函数,该代码将花费约 7 秒钟运行。
thisTakesXSeconds
启动了一个异步进程,需要 X 秒钟才能完成(虽然你“返回”结果的事实似乎表明不是这样),我们将寻找管理完成过程的方法。async
函数的原因。 :-)thisTakesXSeconds
函数返回一个 Promise,并且如果函数可以并行运行,则可以执行以下操作: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)
我使用的一种处理在多个异步调用执行后执行某些代码的技术是使用“已完成”计数器或对象。
每个函数都执行包含回调的操作。
if (counter == numberOfFuntionsIWantedToComplete)
doTheAfterWeHaveAllDataThing`
http.post
需要所有先前的函数完成(否则data
将不完整)。 - JuicyPromise.all
真的非常简单。 - BergithisTakesXSeconds
函数返回它们的结果)。不需要回调,代码将花费约7秒钟运行。 - T.J. Crowder