在异步函数外使用await

3
有没有办法让JavaScript的await关键字在async函数外工作?我希望能够冻结整个调用堆栈(而不仅仅是async函数的其余部分),并在特定的承诺返回值后恢复。可惜这样强大的await目前还没有实现或者功能受限。我尝试过使用nodent.js,但由于我的自定义加载器和动态函数,它不切实际。

1
"我想要能够冻结整个调用栈..." 这意味着代码的总体设计存在问题,因为您真的不希望冻结NodeJS的Javascript线程。请记住,它只有一个。 - T.J. Crowder
1
冻结调用堆栈需要冻结线程,因为 JavaScript 采用了“运行至完成”的语义。一旦从作业队列中取出作业,必须先执行完毕(例如,堆栈展开)才允许该线程执行其他任何操作。(JavaScript 并非固有单线程,但 NodeJS 仅运行单个线程。) - T.J. Crowder
2
冻结调用堆栈并不是 await 的实际工作方式。你所要求的是协程。有一些协程库可用,但据我所知,没有任何接近 async/await 美观语法的东西。 - Stephen Cleary
1
这让我有点想起了 #include "pascal.h" (你试图让 JS 看起来像它不是的东西)。 - robertklep
2
@JohnSmith 你为什么想要这样做?你的实际问题是什么? - Bergi
显示剩余5条评论
2个回答

7

有没有办法使javascript的await关键字在异步函数之外工作?

遗憾的是,答案是:没有。

请参阅文档:

await表达式会导致异步函数执行暂停,等待Promise解决,并在值被解决时恢复异步函数执行。[强调添加]

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await

我希望能够冻结整个调用栈(而不仅仅是异步函数的其余部分),并在特定 promise 返回值后恢复。

但如果整个调用栈都被冻结,你的 promise 如何返回值呢?它将永远被卡住。

更多细节

要使用 await,你需要位于 async function 中。

至少你需要这样做:

async function main() {
  // use await here
}
main();

在您的主要代码中。

或者,使用IIFE——感谢Robert Klep的建议:

void async function main() {
    // use await here
}();

或者,如果你喜欢标点:

(async () => {
    // use await here
})();

其他选项

在Node中,还有一些其他处理并发的选项,例如:

然而,这些操作不会冻结调用栈,因为它们会产生与使用kill -STOP命令暂停进程的效果相同。


@T.J.Crowder 是的,这就是我刚刚在更新中添加的内容。 :) 再次感谢您的评论。 - rsp
1
@JohnSmith 如果你的调用栈被冻结了,那么你的 Promise 怎么可能返回一个值呢?它会像其他所有东西一样被冻结。 - rsp
1
@JohnSmith:那将违反JavaScript规范(详见我在问题评论中的说明)。 (是的,Firefox曾经使用alert做过类似的事情。希望现在不再这样做了,因为运行到完成是规范的重要方面。 :-) ) - T.J. Crowder
1
@rsp 你也可以使用异步IIFE:void async function main() { ... }() - robertklep
1
@JohnSmith:我认为rsp、robertklep和我都很清楚。我们第一次就听到你的意见了。我们告诉你的是:规范不允许你这样做。就JavaScript而言,冻结调用堆栈需要冻结线程。虽然在其他一些语言中并非如此,但在JavaScript中确实如此。因此,尽管你不想冻结线程,但这将是你所说的想要做的事情的必然结果。 - T.J. Crowder
显示剩余8条评论

3

如果您正在寻找一种hack,而不是适合承诺的基于并发的解决方案,请查看node-fibers(有类似的东西,但据我所知,这是最受欢迎的,并建立了多个抽象)。它确实允许您在任何同步函数中暂停当前纤维,直到在不同纤维中运行的某些异步事件发生。当然这是一个可怕的想法,但是...


当然可以。或者他们可以切换到在JVM上运行并使用多个线程。 - T.J. Crowder
@T.J.Crowder 你的意思是,从node切换到rhino?但实际上,纤程(fibers)仍然比线程更好,因为它们允许你显式地yield(就像协程一样)。 - Bergi
我已经看过了node-fibers。它们似乎是我正在寻找的东西(包括上下文切换等),尽管我想象中实现起来可能不是很容易。 - John Smith
@Bergi: 不是Rhino,那个已经过时了。是Nashorn。(但我不是认真的。虽然我一直在挑战JS是单线程的错误说法,但除非你有比不喜欢异步完成更广泛的原因离开Node去JVM,否则我不建议这样做。) - T.J. Crowder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接