我刚刚开始学习Javascript的异步特性,遇到了别人所说的回调地狱。有人可以对以下处理嵌套回调的方法提供一些想法吗?这种方法是否存在可能、问题或缺点?
假设我想异步随机生成一个数字。然后,通过函数修改生成的数字。
function delayedFunctionalites(wait, ...funcs) {
setTimeout(() => {
let randNum = Math.floor(Math.random() * 10);
console.log(`randNum is ${randNum}`);
let updatedRandNum = funcs.reduce((acc, func) => func(acc), randNum);
console.log(`updatedRandNum is ${updatedRandNum}`);
}, wait);
}
const addOne = (input) => input + 1;
const multBy2 = (input) => input * 2;
const addFive = (input) => input + 5;
delayedFunctionalites(2000, addOne, multBy2, addFive);
// Output: randNum is 8
// Output: updatedRandNum is 23
我认为您从评论中获得了一些很好的见解,但为了完整起见,这里有一些您可以进行承诺链的不同方法。
此函数在 1 秒延迟后将数字加 4。这在下面的示例中使用。
const testFunction = async (input: number) => {
return new Promise<number>((resolve) => {
setTimeout(() => {
resolve(input + 4);
}, 1000);
});
};
.then()
一遍又一遍这是通常将 Promise 链接在一起的方式。每个都在下一个之后,并使用前一个的结果。
const callbackChaining = async () => {
const value = 5;
console.log('Value is', value);
const result = await testFunction(value)
.then(async (result) => {
console.log('Value is', result);
return testFunction(result);
})
.then(async (result) => {
console.log('Value is', result);
return testFunction(result);
})
.then(async (result) => {
console.log('Value is', result);
return testFunction(result);
});
console.log('Result is', result);
};
for
循环与 await
您可以使用带有
await
的普通循环来获取每个操作的结果,然后对其调用下一个操作。
请注意,有一条 eslint 规则警告不要在循环中使用
await
,因此您需要研究一下它是否与您的情况相关。
const forLoop = async () => {
let value = 5;
const operations = [testFunction, testFunction, testFunction, testFunction];
for (const operation of operations) {
console.log('Value is', value);
// eslint-disable-next-line no-await-in-loop
value = await operation(value);
}
console.log('Result is', value);
};
Array.prototype.reduce()
您在问题中使用了
reduce
。这是一种类似的使用方法,可以将承诺列表的结果链接在一起。
const arrayReduce = async () => {
const value = 5;
const operations = [testFunction, testFunction, testFunction, testFunction];
const result = await operations.reduce(async (result, operation) => {
return result.then(async (value) => {
console.log('Value is', value);
return operation(value);
});
}, Promise.resolve(value));
console.log('Result is', result);
};