2017-06-19 56 views
1

所以具有以下通过一个对象的代码来循环:环路通过异步请求

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') 
     } 
    }) 
} 

我以前有过这个问题,但没有能够解决它,我怎么能以某种方式做到这一点?

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

+1

有人可能会跳过一个完整的答案,但这里有一个快速提示。在这些情况下,您通常需要的是递归解决方案:在回调中调用您的sendTextMessage函数。 –

+1

评论 - 为什么对您来说消息以正确的顺序发送给API很重要?由于网络延迟,他们可能会以不同的顺序到达Facebook,并且文本可能以不同的顺序到达设备,我认为这些级别没有保证。 –

+1

同时,循环对象的顺序不能保证。使用数组来处理顺序非常重要 – MarkoCen

回答

0

我结束了以下@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

您可以使用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) 
    }) 

} 
0

有一个问题我已经在过去解决了这个方式是使用间隔定时器,有点像这样:

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') 
     } 
    }) 
}