如何在JavaScript异步函数中返回承诺?为什么异步方法不包含返回的承诺?
我有以下代码。我的目的是启动一个任务(涉及几个等待
调用,然后才能真正启动)。当它完成启动时,我需要更新UI,以告诉用户任务已经启动并正在等待结果。结果将稍后出现,因此我想返回另一个Promise
,因此该应用程序知道何时更新UI并返回结果:
async function startSomethingAsync() {
await new Promise(r => globalThis.setTimeout(r, 1000));
console.log("Task started");
const finishedPromise = new Promise<number>(r => {
globalThis.setTimeout(() => r(100), 3000);
});
return finishedPromise;
}
(async() => {
// resultPromise is number instead of Promise<number>
const resultPromise = await startSomethingAsync();
// My intention: update UI after starting the task
console.log("Task started");
// Then when the result is there, do something else
// Currently this is not compiled because resultPromise is not a Promise
resultPromise.then(r => console.log("Result arrived: " + r));
})();
但是上面的代码不起作用。不知何故,resultpromise
是号码
(解决后100),而不是Promise&lt; numbers&gt;
。 TypeScript还识别startemethingAsync
返回promise&lt; number&gt;
而不是promise&lt; promise&lt;
为什么会发生这种情况? async
方法不应该在返回的承诺之外包裹另一个承诺吗?我如何实现自己要做的事情,这是一种“好”模式?
我什至尝试自己包装它:
async function startSomethingAsync() {
await new Promise(r => globalThis.setTimeout(r, 1000));
console.log("Task started");
const finishedPromise = new Promise<Promise<number>>(r1 => r1(new Promise<number>(r2 => {
globalThis.setTimeout(() => r2(100), 3000);
})));
return finishedPromise;
}
该功能仍然返回Promise&gt;
,而不是Promise&lt; Promise&lt; number&gt;&gt;
。
I have the following code. My intention is to start a task (which involves a few await
calls before it can actually start). When it finishes starting it, I need to update the UI to tell user that the task has started and is waiting for result. Result will come in later so I want to return another Promise
so the app knows when to update the UI with returned result:
async function startSomethingAsync() {
await new Promise(r => globalThis.setTimeout(r, 1000));
console.log("Task started");
const finishedPromise = new Promise<number>(r => {
globalThis.setTimeout(() => r(100), 3000);
});
return finishedPromise;
}
(async() => {
// resultPromise is number instead of Promise<number>
const resultPromise = await startSomethingAsync();
// My intention: update UI after starting the task
console.log("Task started");
// Then when the result is there, do something else
// Currently this is not compiled because resultPromise is not a Promise
resultPromise.then(r => console.log("Result arrived: " + r));
})();
However the above code does not work. Somehow resultPromise
is number
(100 after resolved) instead of Promise<number>
. TypeScript also recognize startSomethingAsync
returning Promise<number>
instead of Promise<Promise<number>>
.
Why is this happening? Shouldn't the async
method wrap another Promise outside of the returned Promise? How do I achieve what I am trying to do and is it a "good" pattern?
I even tried wrapping it by myself:
async function startSomethingAsync() {
await new Promise(r => globalThis.setTimeout(r, 1000));
console.log("Task started");
const finishedPromise = new Promise<Promise<number>>(r1 => r1(new Promise<number>(r2 => {
globalThis.setTimeout(() => r2(100), 3000);
})));
return finishedPromise;
}
The function still returns Promise<number>
instead of Promise<Promise<number>>
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
正如我们在评论中讨论的那样 - 您必须将结果承诺包裹在功能或对象中。
As we discussed in the comments - you have to wrap the resulting promise in a function or an object.
否。如果您从
async
函数中返回承诺,则通过调用async
函数创建的承诺只是 解决了该承诺为了解决并将其成就或拒绝作为自己的诺言的其他诺言; how-to-talk-about-promises/“ rel =“ nofollow noreferrer”>在这里)。它没有建立承诺,以实现承诺。承诺永远不会通过承诺实现(无论async
函数如何)。如果要使用
startemethingSync
的承诺,请不要等待
IT:请注意,如果
startermethingsomeNagync
在启动其启动之前具有异步延迟工作(这是非常不寻常的),“任务启动”日志将在异步延迟发生之前发生。如果您不想要它,请将该部分与功能分开,以便您可以在中间登录“任务启动”。例如,您可能具有执行初始位的单独函数,然后将任何内容从开始> startemethingsasync
:或者,如果您的过程是多步骤,则每个步骤都可以返回函数(或下一步的方法):(
实际上,这与使用异步生成器非常相似。)
这些都是主题上的变化,但是外卖消息是,另一个承诺永远无法实现承诺。您会注意到,您从
获得的函数的标准名称
是resolve
和recount
,而不是实现
>和<代码>拒绝。这是因为当您将承诺传递到resolve
中(或从async
函数返回一个,这是同一件事)时,它 sesolves 承诺 其他诺言,而不是通过其他诺言实现诺言。No. If you return a promise from an
async
function, the promise created by calling theasync
function is just resolved to that promise (it waits for that other promise to settle and takes its fulfillment or rejection as its own; more on promise terminology on my blog here). It doesn't set up the promise to be fulfilled with a promise. A promise is never fulfilled with a promise (regardless ofasync
functions).If you want to use the promise from
startSomethingAsync
, simply don'tawait
it:Note that if
startSomethingAsync
has an asynchronous delay before it starts its work (which would be highly unusual), the "Task started" log will occur before that asynchronous delay occurs. If you don't want that, separate out that part from the function so you can get your "Task started" logging in the middle. For instance, you might have a separate function that does the initial bit, and then you pass anything from that intostartSomethingAsync
:Alternatively, if your process is multi-step, each step could return a function (or an object with methods) for the next step:
(In fact, that's very similar to using an async generator.)
These are all variations on a theme, but the take-away message is that a promise can never be fulfilled with another promise. You'll notice that the standard name for the functions you get from
new Promise
areresolve
andreject
, notfulfill
andreject
. That's because when you pass a promise intoresolve
(or return one from anasync
function, which is effetively the same thing), it resolves the promise to that other promise, rather than fulfilling the promise with that other promise.所有
async
功能隐式返回承诺。如果您明确归还承诺,则不会包装它。如果承诺另一个承诺,他们嵌套的诺言是扁平的 -
All
async
functions implicitly return a promise. If you explicitly return a promise, it will not be wrapped.If a promise resolves another promise, they nested promises are flattened -