2017-06-19 51 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') 
     } 
    }) 
}