在node REPL中同步等待Promise

3
如果我启动一个Node REPL并调用返回Promise的函数,该函数(显然)立即返回,并在控制台中显示有关Promise的一些信息:
$> node
> var foo = () => new Promise((resolve, reject) => setTimeout(resolve('yay'), 1000));
undefined
> foo().then(console.log)
Promise {
  <pending>,
  domain:
   Domain {
     domain: null,
     _events: { error: [Function: debugDomainError] },
     _eventsCount: 1,
     _maxListeners: undefined,
     members: [] } }

有没有办法让Node同步等待Promise解决(或拒绝),以便我可以将结果打印到控制台?
我看到类似this one的问题,但那里的解决方案都建议在结果上附加.then()调用来完成我想要的操作(例如记录日志)。然而,这似乎行不通--请注意,我在我的示例中已经这样做了,但我从未得到任何日志输出,因此我需要一些其他机制来使进程持续运转足够长的时间,以便我可以看到输出(例如示例中的字符串'yay')。

哪个Node版本?Node v7.6.0+支持await - hisener
如果您的Node版本支持,可以使用await。但这也不是真正的同步,只是语法糖。或者您可以继续使用返回的Promise对象的then()方法来处理其解析出的值。 - Thomas
2
@JeremyThille,这个问题特别是关于在REPL中检查和交互值的。无论它是否符合Node/JS的习惯用法,在这种情况下并不是很相关。 - Emil Lundberg
@Thomas:不行,因为要使用await,我必须处于一个async上下文中,而且我无法弄清如何创建一个不仅仅打印承诺并退出的async上下文。 - Tomas Aschan
可能是重复问题,参考如何在继续函数之前等待JavaScript Promise解决? - Emil Lundberg
显示剩余7条评论
3个回答

2

从8.4.0版本开始,Node REPL在打印时会显示已解析的Promise的值:

$ node --version
v8.4.0
$ node
> var foo = () => new Promise((resolve, reject) => setTimeout(() => resolve('yay'), 3000));
undefined
> var p = foo()
undefined
> p
Promise {
  <pending>,
    domain: // Omitted for brevity
}
> // Wait 3 seconds...
> p
Promise {
  'yay',
  domain: // Omitted for brevity
}

正如您所看到的,当Promise被解决时,<pending>将被替换为'yay'

1
你的代码不完全正确,因为你的 Promise 立即解决而不是在 1000 毫秒后解决。我认为你的意思是: var foo = () => new Promise((resolve, reject) => setTimeout(() => resolve('yay'), 1000)); - kYuZz

2

实际上,以上示例中存在一个错误。您立即解决了承诺,因此setTimeout不起作用。如果您将该行更改为

var foo = () => new Promise((resolve, reject) => setTimeout(() => resolve('yay'), 1000));

那么行为就变成了您所描述的:

> var foo = () => new Promise((resolve, reject) => setTimeout(() => resolve('yay'), 1000));
undefined
> foo()
Promise {
  <pending>,
  domain: 
   Domain {
     domain: null,
     _events: { error: [Function: debugDomainError] },
     _eventsCount: 1,
     _maxListeners: undefined,
     members: [] } }

为了解决这个问题,你可以使用async/await来包装foo,像这样:

为此,您可以使用async/await来包装foo,如下所示:

> var bar = async () => {
... var res = await foo();
... console.log(res);
... }

现在,running bar将让您按预期打印(或检查)结果:

> bar()
Promise {
  <pending>,
  domain: 
   Domain {
     domain: null,
     _events: { error: [Function: debugDomainError] },
     _eventsCount: 1,
     _maxListeners: undefined,
     members: [] } }
> yay

与直接调用foo不同,最后一行将在一秒钟后打印。


1
从Node.js v10.0开始,您可以使用选项--experimental-repl-await在REPL中启用await

https://nodejs.org/api/cli.html#cli_experimental_repl_await

$> node --experimental-repl-await
> var foo = () => new Promise((resolve, reject) => setTimeout(resolve('yay'), 1000));
undefined
> await foo()
'yay'

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