【问题标题】:Why does this myFunction().then() operation seem to hang indefinitely?为什么这个 myFunction().then() 操作似乎无限期挂起?
【发布时间】:2016-02-05 21:03:18
【问题描述】:

我在处理一些非生产代码时遇到了一些问题。我想处理大约 3000 个数组元素。如果我 strace 节点进程,它位于epoll_wait(5,所以大概我阻塞了主线程。

任何人都可以建议a)我做错了什么或b)我如何查看执行堆栈/事件循环以准确检查代码为何挂起?我尝试调试并逐步执行代码并让该过程正常工作,但我并不明智。

使用 Promises.map 更新代码:

connection.query(firstPostQuery,{ x: whiteListString }, function( err, rows ) {

    Promise.map(rows, function(result) {


        return sfs.isSpammer({
            ip: result.ip,
            email: result.email,
            username: result.poster
        }).then(function(res) {
console.log(parseInt(res.username.appears) == 1); //evaluates to true

            if (parseInt(res.username.appears) == 1 ) {

                console.log(res.toJSON());
                fs.appendFile(__dirname + '/stopforumspam.txt', res.poster + '\n',
                    function(err) {
                        if (err) {
                            throw err;
                        }
                        return true;
                    });

            } else {
                fs.appendFile(__dirname + '/stopforumspam.txt',
                    'nope\n',
                    function(err) {
                        if (err) {
                            throw err;
                        }
                        return true;
                    });
            }
        });
        //Iteration completed
    }, {concurrency: 5}).then(function(result) {
        //Do something with result
        console.log(result);
    }).catch(function(err) {
        //Error
    });
});

我正在运行 node.js 4.2.4。我一直在尝试 Bluebird Promise,但不确定这在这种情况下是否有用,因为我还不完全理解 Promise。

【问题讨论】:

  • 您一次发出所有 3000 个请求,因此可能只是您请求的任何机器/服务正忙于处理所有这些请求,或者可能是 sfs 服务无法处理 3000请求并挂起。
  • @slebetman 谢谢。您将如何减慢速度并小批量提出请求?我尝试了一些声称可以这样做但也没有解决问题的不同库。
  • @codecowboy,实际上,你混合了同步。循环,承诺,这就是你有故障的原因。
  • @NazarSakharenko 谢谢。请您在回答中详细说明这一点吗?
  • 有一个关于 Promises 的好话题,html5rocks.com/en/tutorials/es6/promises。在您的情况下,for 循环,您在每次迭代时执行新的 'sfs.isSpammer' 调用,而无需等待调用结果。因此,在某一时刻,一些“sfs.isSpammer”承诺得到解决(在同一时刻),并导致线程阻塞。

标签: node.js


【解决方案1】:

您可以尝试使用 (bluebird) Promise.map 来迭代异步。

connection.query(firstPostQuery, {x: whiteListString}, function(err, rows) {

    Promise.map(rows, function(result, index) {
        console.log('item', index);
        return new Promise(function(resolve, reject) {
            sfs.isSpammer({
                ip: result.ip,
                email: result.email,
                username: result.poster
            }).then(function(res) {
                console.log('In Promise', res);
                console.log(parseInt(res.username.appears) == 1); //evaluates to
                                                                  // true
                if (res && parseInt(res.username.appears) == 1) {
                    return fs.appendFile(__dirname + '/stopforumspam.txt', res.poster + '\n',
                            function(err) {
                                console.log('In AppendFile spamer');
                                if (err) {
                                    reject(err);
                                }
                                resolve(true);
                            });
                } else {
                    return fs.appendFile(__dirname + '/stopforumspam.txt',
                            'nope\n',
                            function(err) {
                                console.log('In AppendFile good user');
                                if (err) {
                                    reject(err);
                                }
                                resolve(true);
                            });
                }
            });
        });
    }).then(function(res) {
        console.log(res);
    }).catch(function(err) {
        console.log(err);
    });
});

【讨论】:

  • 谢谢。我在我的问题中添加了一些更新的代码。但是,if(parseInt(res.username.appears) == 1) 之后的代码没有运行,即没有任何内容写入我的文件。这是否可能是由 stopforumspam 库的体系结构引起的? github.com/deltreey/stopforumspam
  • 不,库一切正常,我只是忘了用 Promise 包装 fs.appendFile(因为这是异步函数),答案已更新。现在应该可以了,执行顺序正确;
  • 谢谢。我认为您需要包含 browserify 才能使该 jsFiddle 正常工作。
  • 这样使用 appendFile 是否也有问题?另一个问题是脚本没有退出。
  • 'connection.query'中没有回调,你应该添加它,根据你想要在函数完成后执行的操作。
猜你喜欢
  • 2021-09-14
  • 2011-11-20
  • 2015-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-11
  • 2014-01-04
  • 1970-01-01
相关资源
最近更新 更多