【问题标题】:Break While loop in NodeJS when Async function is done [duplicate]完成异步功能后,NodeJS中的While循环中断[重复]
【发布时间】:2018-05-30 13:50:59
【问题描述】:

我有以下节点 js 脚本:

const rp = require('request-promise')
let result = ''
let asyncdone = false
async function m() {
    return await rp.get('http://google.com')
}

m().then((html) => {
    result = html
    asyncdone = true
}).catch((e) => console.log(e))

while (!(asyncdone)) {
    console.log('processing...')
}
console.log(result)

运行时,循环是无限的。
'processing...' 会继续打印,即使异步函数应该将 asyncdone boolean 设置为 true,从而打破循环,然后记录结果

我不明白什么?

【问题讨论】:

  • 当你已经使用了一个使用承诺时,为什么还要使用 while 循环?这就是 async/await 的全部意义所在,您可以等待异步任务完成,而不必像这样等待......
  • 天啊!这是有史以来最糟糕的主意! while 循环完全阻塞。它将无限循环,永远不会将控制权交还给事件循环以运行您的异步代码。 ????‍♂️

标签: javascript node.js async-await ecmascript-2017


【解决方案1】:

while 实际上是在做正确的事。

由于它连续检查条件而没有任何延迟并且每次都为真,它在控制台上打印信息,如果它在一秒钟内进行百万检查并且满足条件,控制台将打印字符串。

因此,我们需要添加一个超时/间隔(称为 pollInterval),以便它仅在所需时间后检查。

对于您的问题,我有不同的解决方案。您想在承诺进行时显示进度/填充文本。

const rp = require('request-promise')

// The base wrapper to stop polluting the environment
async function getHTML(url) {

    // A sample filler function
    function doSomethingElse() {
        console.log(`Processing`);
    }

    // a filler function to use it later inside
    function ensureData({
        fillerFn,
        pollInterval = 500
    }) {
        let result;

        // grab the data and set it to result async
        rp.get(url)
            .then((html) => {
                result = html
            })
            .catch((e) => console.log(e))

        return new Promise(function(resolve, reject) {
            // a self-executing function
            (function waitForFoo() {
                // if there is result, resolve it and break free
                if (result) return resolve(result);

                // otherwise run the filler function
                fillerFn()

                // execute itself again after the provided time
                setTimeout(waitForFoo, pollInterval);
            })();
        });
    }

    // return or run it
    ensureData({
            fillerFn: doSomethingElse,
            pollInterval: 500
        })
        .then((result) => {
            console.log(result)
        })
}

getHTML('http://httpbin.org/ip');

【讨论】:

  • 解释得很好。非常感谢先生!
【解决方案2】:

如果您只想登录processing... 一次,我会将代码更改为以下代码。

var statuslogged = false;
while (true) {
  if (!statuslogged) {
    console.log('processing...');
    statuslogged = true;
  }
  if (asyncdone) {
    console.log(result)
  }
}

【讨论】:

  • 它不会跳出 while (!(asyncdone)) {.......} 循环。结果不会被记录。目的是重复打印 processing... 直到结果可用。
  • @nas96 我的错先生,我误解了你的问题我更新了答案中的代码
猜你喜欢
  • 2016-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-28
  • 2020-04-02
  • 2022-01-26
  • 1970-01-01
  • 2021-06-02
相关资源
最近更新 更多