我正在编写一个返回值和数组的函数。某些值是在回调中计算的。但我不知道如何使程序异步,所以我的所有结果都在数组中,并且在返回后不会添加。
let array = []
for (stuff : stuffs) {
if (condition) {
array.add(stuff)
} else {
api.compute(stuff, callback(resp) {
array.add(resp.stuff)
}
}
}
res.json({ "stuff": array })
在此示例中,在异步调用完成之前,数组将写入响应。
如何异步进行此操作?
答案 0 :(得分:1)
您必须使用以下方法之一:
我认为最酷的是async/await
。首先我们修改你的函数,所以它返回一个promise:
const compute = function(stuff) {
return new Promise( (resolve, reject) => {
api.compute(stuff, callback(resp){
resolve(resp.stuff)
});
});
};
然后我们使用异步处理程序修改您的路由:
app.get('/', async function(req, res, next) {
const array = [];
for (const stuff of stuffs) {
if (condition) {
array.add(stuff);
} else {
const stuff = await compute(stuff);
array.push(stuff);
}
}
res.json({ stuff: array });
});
注意:您可能需要将节点版本更新为最新版本。
<强>更新强>
那些不知道的人,事件循环如何工作,执行这个片段,然后完成:
const sleep = async function(ms) {
console.log(`Sleeping ${ms}ms`);
return new Promise( resolve => setTimeout(resolve, ms));
};
async function job() {
console.log('start');
for (let t = 0; t < 10; t++) {
await sleep(100);
}
}
job();
console.log('oops did not expect that oO');
你会感到惊讶。
答案 1 :(得分:1)
这是一个没有使用回调的包的答案
创建一个能递归处理所有内容的功能。
getArray(stuffs, callback, index = 0, array = []) {
// Did we treat all stuffs?
if (stuffs.length >= index) {
return callback(array);
}
// Treat one stuff
if (condition) {
array.add(stuffs[index]);
// Call next
return getArray(stuffs, callback, index + 1, array);
}
// Get a stuff asynchronously
return api.compute(stuffs[index], (resp) => {
array.add(resp.stuff);
// Call next
return getArray(stuffs, callback, index + 1, array);
});
}
怎么称呼它?
getArray(stuffs, (array) => {
// Here you have your array
// ...
});
编辑:更多解释
我们想要做的是将你所拥有的循环转换为处理异步函数调用的循环。
目的是一个getArray
调用将处理stuffs
数组的一个索引。
在处理了一个索引之后,该函数将再次调用自身来处理下一个索引,直到所有索引都被处理完毕。
-> Treat index 0 -> Treat index 1 -> Treat index 2 -> Return all result
我们正在使用参数在整个过程中传递信息。 Index
知道我们必须处理哪个数组部分,并array
保留我们计算的数据。
编辑:改进100%异步解决方案
我们在这里所做的是将初始for循环简单转换为异步代码。它可以通过使它完全异步来改进,这使它变得更好但稍微更难。
例如:
// Where we store the results
const array = [];
const calculationIsDone = (array) => {
// Here our calculation is done
// ---
};
// Function that's gonna aggregate the results coming asynchronously
// When we did gather all results, we call a function
const gatherCalculResult = (newResult) => {
array.push(newResult);
if (array.length === stuffs.length) {
callback(array);
}
};
// Function that makes the calculation for one stuff
const makeCalculation = (oneStuff) => {
if (condition) {
return gatherCalculResult(oneStuff);
}
// Get a stuff asynchronously
return api.compute(oneStuff, (resp) => {
gatherCalculResult(resp.stuff);
});
};
// We trigger all calculation
stuffs.forEach(x => x.makeCalculation(x));