【问题标题】:Issue trying to run synchronous REST requests in Node尝试在 Node 中运行同步 REST 请求时出现问题
【发布时间】:2015-07-02 17:04:25
【问题描述】:

首先,我在异步编程方面没有经验,所以如果我遗漏了一些明显的东西,我很抱歉。

我经常看到这个问题出现。我知道人们不喜欢在 Javascript 中强制同步,但在这种情况下这是必要的。我正在对生产数据库进行大量调用,由于使用频率很高,它不能承受太多负载。因此,我在循环中设置我的代码以发出请求,等待确认完成,休眠 2 秒,然后发出下一个请求。这是因为我将在大约 10 到 20 分钟的时间内每周从该服务器提取大量数据。

这是我拥有的代码。 Sleep 是一个使用 Date 类强制程序等待的函数。

    var thread = function(cb){
        cb();

    };


    do{

        var x = thread(function(){
            request.post(options, function(e, r, body){
                console.log(e);
                console.log(r.statusCode);
                issues.push(body["issues"]);
                maxResults = body["total"];
                options.body.startAt += 25;
                console.log("Going to sleep");

            });
            sleep(2000);
        });
        console.log("Waking up and moving to the next cycle");

    }while(issues.length < maxResults);
    console.log("Finished with the requests");
}

虽然我设置了回调,但我的代码仍在异步运行请求。因为我将 maxResults 保留为空,所以很明显我的回调不起作用。这是我的输出:

Waking up and moving to the next cycle
Finished with the requests
Going to sleep

【问题讨论】:

  • 你不能那样做。相反,你应该使用 Promise。
  • 我经常看到人们这么说,但我一直无法找到为此目的构建承诺的正确方法,即使在阅读了 bluebird 自述文件之后也是如此。在我看来,promise 更像是一种通过函数链接值的方式,而不是像我想要使用它们那样充当异步线程的连接。可以举个例子吗?
  • 感谢您的帮助,但该示例并不真正适用于我的情况。我将循环的 while 条件基于每个 post 调用的结果。因此,我无法将所有异步函数完全放入列表中,以便在将来的某个时间按顺序解析。我需要在创建每个函数后对其进行解析。我一直在寻找一段时间,但我仍然无法找到如何强制使用 bluebird 解析函数。这可能不符合异步编码约定,但它对我正在使用的数据库至关重要。我需要进行 1000 次深度递归调用吗?

标签: javascript node.js asynchronous express


【解决方案1】:

你需要做一个递归异步函数。

看起来像这样:

function fetch(existingIssues) {
    return sendRequest().then(function() { 
        existingIssues.push(...);
        if (existingIssues.length >= maxResults)
            return existingIssues;
        else
            return fetch(existingIssues);
    });
}
fetch([]).then(...);

【讨论】:

  • 这看起来很危险。我正在处理大型对象、包含约 30 列的表行,包括描述和摘要列。这需要能够处理总共约 5-10 GB 的数据,因此递归函数会很快变得臃肿和缓慢。我的意思是,如果这是唯一的方法,那就是唯一的方法……但是没有其他解决方案吗?
  • @user3723527:不。异步递归不会使调用堆栈膨胀;每个异步边界都以一个空的调用堆栈开始。这没有什么问题。
  • 我相信你的话,但我很好奇它是如何工作的。如果我有异步函数 var foo = function(){ var x = 2 ; return x + foo();} 不会用设置为 2 的无限变量填充堆栈吗? Javascript 如何避免这种情况?是否足够聪明地区分和垃圾收集递归调用后丢弃的函数或不在返回值中使用作用域变量?
  • @user3723527:这不是异步的。异步的全部意义在于回调运行稍后,根据定义,在堆栈帧退出之后。并且异步调用之间没有封闭关系;这只发生在词法嵌套中。您应该了解 Node.js 事件循环。
猜你喜欢
  • 2018-09-23
  • 2017-06-08
  • 1970-01-01
  • 1970-01-01
  • 2021-05-25
  • 1970-01-01
  • 2023-02-08
  • 2017-03-30
  • 1970-01-01
相关资源
最近更新 更多