【问题标题】:Loop through asynchronous request循环异步请求
【发布时间】:2017-11-22 00:32:52
【问题描述】:

所以我有以下代码来循环一个对象:

for(var x in block){
    sendTextMessage(block[x].text, sender, function(callback){
        //increment for?
    })
}

对于每次迭代我想做一个请求(发送一条facebook消息),只有在那个请求完成后,我才想进行下一个迭代,这是因为没有任何回调,消息将不会被发送正确的继承。

function sendTextMessage(text, sender, callback) {
    let messageData = { text:text}
    request({
        url: 'https://graph.facebook.com/v2.6/me/messages',
        qs: {access_token:token},
        method: 'POST',
        json: {
            recipient: {id:sender},
            message: messageData,
        }
    }, function(error, response, body) {
        if (response.statusCode >= 200 &&  response.statusCode < 300){
            if(callback) callback('success')
        }
    })
}

我以前遇到过这个问题,但无法解决,我该怎么办?

如果您有任何问题,请提出。谢谢。

【问题讨论】:

  • 有人可能会给出完整的答案,但这里有一个快速提示。在这些情况下,您通常需要的是递归解决方案:在回调中调用 sendTextMessage 函数。
  • 一条评论 - 为什么以正确的顺序将消息发送到 API 对您很重要?由于网络延迟,它们可能会以不同的顺序到达 Facebook,并且文本可能会以不同的顺序到达设备,我认为在这些级别上无法保证。
  • 同时,不保证循环对象的顺序。使用数组进行订单逻辑

标签: javascript node.js loops express


【解决方案1】:

我最终遵循了@Matt Diamond 的建议并执行了一个如下所示的递归函数:

function buildFlow(block, sender){
    var i = 0;
    recursive()
    /*  for(var x in block){
        sendTextMessage(block[x], block[x].type, sender)
        console.log(x)
    }*/
    function recursive(){
        if (i<Object.keys(block).length){
            sendTextMessage(block[Object.keys(block)[i]], block[Object.keys(block)[i]].type, sender, function(){
                i++
                recursive()
            })

        }else{
            i = 0
        }
    }
}

感谢所有给予帮助的人,非常感谢。

【讨论】:

    【解决方案2】:

    我过去解决这个问题的一种方法是使用间隔计时器,有点像这样:

    var isSending = false;
    var sendMessages = setInterval(function() {
      if(!isSending) {
        isSending = true;
        sendTextMessage(block.pop().text, sender, function(){
          if(block.length) {
           isSending = false;
          } else {
            clearInterval(sendMessages);
            //Done
          }
        })
      }
    })
    
    function sendTextMessage(text, sender, callback) {
        let messageData = { text:text}
        request({
            url: 'https://graph.facebook.com/v2.6/me/messages',
            qs: {access_token:token},
            method: 'POST',
            json: {
                recipient: {id:sender},
                message: messageData,
            }
        }, function(error, response, body) {
            if (response.statusCode >= 200 &&  response.statusCode < 300){
                if(callback) callback('success')
            }
        })
    }
    

    【讨论】:

      【解决方案3】:

      您可以使用async 模块,这对您一一提出请求非常有帮助。下面是来自 async 官方文档的示例代码,相当直观易懂。

        function asyncForEach (arr, iterator, callback) {
          queue = arr.slice(0)
              // create a recursive iterator
          function next (err) {
            if (err) return callback(err)
      
                  // if the queue is empty, call the callback with no error
            if (queue.length === 0) return callback(null)
      
                  // call the callback with our task
                  // we pass `next` here so the task can let us know when to move on to the next task
            iterator(queue.shift(), next)
          }
      
              // start the loop;
          next()
        }
      
      function sampleAsync (param, done) {
      // put a callback when function is done its work 
      }
      
        asyncForEach(result, function (param, done) { // result is the array you pass as iterator
          sampleAsync(param, function (message) {
            console.log(message)
            done()
          })
        }, function () {
          console.log('callback')
          callback(SOME_RESULT)
        })
      
      }
      

      【讨论】:

        猜你喜欢
        • 2019-07-21
        • 2017-03-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-07
        相关资源
        最近更新 更多