【问题标题】:NodeJS: working with promises from an interactive consoleNodeJS:从交互式控制台处理 Promise
【发布时间】:2020-05-11 08:29:02
【问题描述】:

我正在学习 NodeJS。我发现真正令人讨厌的一件事是,在使用 交互式控制台 的 Promise 时,在调试和/或只是在各种库的接口上闲逛时。工作流程正常;调用一些库来做一些工作,等待结果,查看结果以查看它的实际行为和外观。

例如(仅作为示例)我想以交互方式检查从Jimp 返回的图像数据结构。我发现自己是从控制台执行此操作的:

const Jimp = require('jimp');
const fs = require('fs');
let data = fs.readFileSync('path/to/my/test/images')
let image = null
Jimp.read(data).then((result, error) => { image = result; });
// Work with image here ...

这个样板写起来很烦人。我想我错过了一个窍门。有没有更方便的方法来解决这个问题?可以设置的设置,或者我可以加载的库之类的?

我宁愿这样做:

...
let image = await Jimp.read(data);
// Work with image here ...

但这给出了“SyntaxError: await is only valid in async function”。或者如果不是这样,那么也许:

...
let image = resolveMe(Jimp.read(data))
// Work with image here ...

附: “async / await”不是这个问题的答案。为了评估异步函数,您必须将控制权交还给事件循环,并且您不能在当前 AFAIK 的 interactive 提示符下执行此操作。

【问题讨论】:

  • let image = await Jimp.read(data); 怎么样?必须在 async 函数内才能被允许。基本上,异步代码只是在交互式终端中一次一行的痛苦。我只是发现编写一个 10 行程序并在 node.js 中运行它更容易。如果我想检查一些东西,我会在调试器中运行它并单步执行或设置断点。或者,有时,只需插入一些 console.log() 语句并运行它即可进行检查。
  • 好吧,现在您的编辑表明您不想将控制权交还给事件循环。如果不将控制权交还给事件循环,则无法完成任何异步操作,因此您所要求的无法完成。他们通过将事件插入事件循环来完成工作,并且在您将控制权返回给事件循环之前无法处理该事件。所以,根据定义,你必须这样做。 Javascript 不能按您要求的方式工作,因此控制台也不能。
  • 你的想法太字面意思了。是的,当然你必须将控制权交还给事件循环。但是没有理由不能对用户隐藏。我没有说我“不想”将控制权交还给事件循环。我说/意思是异步函数是如何被评估的。
  • 嗯,你要求的东西不能那样工作。我猜,写一个不同的交互式承诺,它会按照你想要的方式工作。我认为我们无能为力。无论如何,我个人从来没有理解交互式控制台对任何其他真正基本的东西的吸引力。我发现只需编写一个简短的程序并运行它、调试它、在其中插入 console.log() 语句、编辑它、再次运行它等等……对我的工作来说比提示更有效。跨度>
  • “那样不行,而且 Node 程序员工具包中没有任何东西可以做到……”将是一个完全可以接受的答案。也许就像您说的那样,编写一个以这种方式工作的控制台包装器太难了,但是如果已经完成了,为什么还要重新发明轮子。因此是 Q。

标签: node.js es6-promise


【解决方案1】:

我为我的 Q 偶然发现了 SO answer。对于节点 v12+,您可以设置 --experimental-repl-await 选项。一直就在我的眼皮底下……总结:

没有:

$ node
Welcome to Node.js v12.18.1.
Type ".help" for more information.
> await Promise.resolve(7)
await Promise.resolve(7)
^^^^^
Uncaught SyntaxError: await is only valid in async function

与:

$ node --experimental-repl-await
Welcome to Node.js v12.18.1.
Type ".help" for more information.
> await Promise.resolve(7)
7

【讨论】:

    【解决方案2】:

    Node.js 真的没有办法等到一个事件,AFAICT。但是在交互模式下,假设你在等待,你所关心的只是对结果做一些事情,所以我试图找到方便的方法来获得它。

    我能想出的最接近的是这样的助手:

    Promise.prototype.a = function() {
        this
            .then(res => {
                Promise.res = res;
                console.log("async", res);
            })
            .catch(console.error)
    }
    

    示例用法:

    Welcome to Node.js v12.2.0.
    Type ".help" for more information.
    > Promise.prototype.a = function() {
    ...     this
    ...         .then(res => {
    .....           Promise.res = res;
    .....           console.log("async", res);
    .....       })
    ...         .catch(console.error)
    ... }
    [Function]
    > 
    > function sleep(ms) {
    ...     return new Promise((resolve) => {
    .....       setTimeout(resolve, ms);
    .....   });
    ... }  
    undefined
    > 
    > async function afterSleep(sec) {
    ...     await sleep(sec * 1000);
    ...     return 100;
    ... }
    undefined
    > afterSleep(2).a()
    undefined
    > async 100
    
    > Promise.res
    100
    

    你仍然不能等待它完成,但至少结果是可用的。

    【讨论】:

      【解决方案3】:

      这就是async-await 的用途。它允许您以一种看起来像同步代码的方式编写异步代码,即使在底层它与使用 Promises 完全相同。 Promise 最终会因所有的函数嵌套而变得非常尴尬。

      你可以写:

      let image = await Jimp.read(data); 
      // do something with image
      

      唯一的要求是你在其中执行的函数必须声明为异步的。这意味着你至少需要有一个功能,你不能在最外层使用await

      【讨论】:

      • 但它必须在异步函数中。您不能只在提示符处写let image = await Jimp.read(data); 。我几乎符合这个问题:我不是在寻找异步/等待。
      • 是的。我添加了一个“P.S”,请阅读。我知道什么是 async / await - 或多或少。尝试在命令提示符下运行let image = await Jimp.read(data);
      • Node 对所有的事情都使用异步。我认为可能会有一个类似于 bluebird 对 promises 的猴子补丁,用于使东西在控制台上看起来是同步的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-01
      • 2012-06-24
      • 2014-10-21
      相关资源
      最近更新 更多