我是 JavaScript 承诺的新手,想知道这是否是在 JavaScript/Node.js 中异步共享结果的常见/惯用方式。
我有一个方法,例如calc
,异步计算项目列表。我只希望结果计算一次,其他cals要么得到已经计算的结果,要么等到结果计算出来。我提出了以下设计(一个演示它的最小示例)。
let result: Promise<number[]>;
async function calc(): Promise<number[]> {
if (result) {
return result;
}
result = new Promise<number[]>(async (resolve, reject) => {
await delay(5000);
resolve([1, 2, 3, 4, 5]);
});
return result;
}
async function delay(time: number) {
return new Promise<void>((resolve, reject) => setTimeout(resolve, time));
}
这个设计有什么缺陷吗?该calc
方法是否总是异步的?即,结果在与调用者不同的堆栈中运行?
该
calc
方法是否总是异步的?
使用承诺calc
返回的结果将始终是异步的(这可能是您真正的意思)。这是由规范保证的:无论承诺是否已经解决then
,catch
回调总是异步调用。
请注意,如果您要返回一个承诺(您在 中的所有代码路径中calc
)并且不在(您不是)await
的直接主体中使用calc
,则您不需要声明calc
为async
。这样做在概念上增加了一层承诺(这在很大程度上是无害的,但是......)。
这个设计有什么缺陷吗?
几个次要的。delay
当然,这只是代表您将要做的实际工作。await delay();
在async
没有try
/ 的承诺执行器回调中使用catch
意味着如果来自delay
rejects的承诺,您将错过它。您想确保处理拒绝(可能在执行程序回调中使用try
/catch
或不在其中使用await
)。
与此相关的是,代码也成为 Promise 创建反模式的牺牲品。由于delay
提供了一个承诺,这里不需要new Promise
in calc
。只需使用delay
.
所以calc
可以看起来像这样:
function calc(): Promise<number[]> {
if (result) {
return result;
}
return result = delay(5000).then(() => [1, 2, 3, 4, 5]);
}
由于您明确处理了承诺,因此我可能不会使用async
它。
现场演示(只是为了好玩;我将延迟设为 800 毫秒而不是 5000 毫秒):
let result;
function calc() {
if (result) {
return result;
}
return result = delay(800).then(() => [1, 2, 3, 4, 5]);
}
function delay(time) {
return new Promise(resolve => {
setTimeout(resolve, time);
});
}
console.log("A");
calc().then(() => { console.log("C"); });
console.log("B");
calc().then(() => { console.log("D"); });
setTimeout(() => {
console.log("E");
calc().then(() => { console.log("G"); });
console.log("F");
}, 1000);
如您所见,它输出A B
,等待 800 毫秒,输出C D
,再等待约 200 毫秒,然后输出E F G
,证明消费者 calc
的承诺始终是异步的。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句