【问题标题】:Need to try and block and asynchronous call需要尝试阻塞和异步调用
【发布时间】:2015-10-13 01:40:01
【问题描述】:

我正在尝试运行以下代码,基本上我运行 api 调用以查看特定时间段内的结果存在多少页,在循环中运行 api 调用以获取每个页面的返回,然后在如果结果的 id 大于 0,则此循环将每个结果(使用 forEach 函数)插入 mongo 数据库。

但是,我遇到的问题是 api 调用是异步的,因此当 insert 函数开始运行时,我收到一个失败消息,说明我试图在 (nspR​​esp.responses) 上运行 forEach 函数的数组是不明确的。

在 api 调用完成运行之前,我可以通过任何方式阻止此 forEach 的运行。我意识到我可能没有正确构建这些数据,因此重组想法也会有所帮助。

function request() {
    uservoiceRequest.get({
        url: "reports/user_satisfaction_responses.json",
        data: {
            page: 1,
            start_date: "2015-01-01T00:00:00-0600",
            end_date: moment().format()
        }
    }, function (err, respData) {
        if (err) return console.log(err)
        console.log(respData.pages)
        for (i = 1; i <= respData.pages; i++) {
            uservoiceRequest.get({
                url: "reports/user_satisfaction_responses.json",
                data: {
                    page: i,
                    start_date: "2015-01-01T00:00:00-0600",
                    end_date: moment().format()
                }
            }, function (err, npsResp) {
                npsResp.responses.forEach(function (e) {
                    if (e.id > 0) {
                        myCollection.insert({
                            created_at: new Date(e.created_at),
                            body: e.body,
                            score: e.score,
                            id: e.id,
                            user: {
                                type: e.user.type
                            }
                        }, function (err, dataInsert) {
                            if (err) return console.log(err);
                        });
                    }
                });
            });
        }
    });
}

【问题讨论】:

  • 使用回调 - 这就是它们的用途。
  • 您可能应该阅读一些关于 Promise 的内容。 developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
  • 这些 API 是异步的。你不应该阻止他们。如果要在 node.js 中编写代码,则需要学习如何使用多个异步操作进行编程。避免它是没有意义的——你应该学习。要使许多异步操作真正按顺序进行,您可以手动对其进行编码(当一个完成时,开始下一个),使用 Async 库为您排序,或者您的 Promise 为您排序。我的首选是 Bluebird Promise 库。
  • 请准确描述您希望发生的事件顺序。您有一个初始异步调用,然后在该响应中嵌入一个带有异步调用的for 循环,并嵌入其中每个带有异步调用的.forEach() 循环。因此,您可能有很多很多异步调用。确切地说,您希望它们如何排序。描述理想的操作顺序,而不是代码的工作方式或您尝试的方式。
  • @jfriend00 - 对不够清晰感到抱歉。我试图首先查看在提供的时间范围内响应存在多少页数据。然后,对于每一页,我要获取数据,验证 id 值是否大于零,然后将其插入到 mongo 数据库中。

标签: javascript node.js asynchronous callback


【解决方案1】:

如果你想在继续之前完成一组操作,我会将我的异步调用映射到一个 Promise 中,然后等待它们。例如使用下划线和 q:

var uservoiceRequestGetPromise = q.bind(uservoiceRequest.get, uservoiceRequest)
uservoiceRequestGetPromise({
            url: "reports/user_satisfaction_responses.json",
            data: {
                page: i,
                start_date: "2015-01-01T00:00:00-0600",
                end_date: moment().format()
            }
}).then(function(npsResp){
   var myCollectionInsertPromise = q.bind(myCollection.insert, myCollection)

   return Q.all(_.map(npsResp.responses, function(e){
        return myCollectionInsertPromise({
                        created_at: new Date(e.created_at),
                        body: e.body,
                        score: e.score,
                        id: e.id,
                        user: {
                            type: e.user.type
                        }
                    }
    }))
}).finally(function(){
   console.log('done')
})

我提供的示例有点草率,但老实说,我试图尽可能多地使用您的代码。您可以真正受益于将示例的复杂性降低到其根本原则,而不是发布您的确切代码 - 人们更容易使用和遵循。

也就是说,我认为您可以将一系列 NodeJs 传统回调转换为 Promise 方法,然后映射到一个数组并收集 Promise,然后最后使用 Q.all 也收集 Promise,然后再继续。

【讨论】:

  • 使用了蓝鸟,但方法相同,这行得通,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-06
  • 1970-01-01
相关资源
最近更新 更多