Facebook Messenger bot不按顺序发送消息

我正在玩一个简单的Facebook Messenger聊天机器人,我无法顺序发送消息。

在这里输入图像描述

在上面的例子中,它应该按顺序打印“你好!”,“1”,“2”,“3”。 我目前正在关注在这里发现的Facebook文档来实现这个简单的短信function。 我已经包含了我的Express Node.JS服务器代码如下:

定义sendTextMessage()函数:

 var request = require("request"); function sendTextMessage(user, text) { messageData = { text: text }; request({ url: "https://graph.facebook.com/v2.6/me/messages", qs: {access_token: PAGE_ACCESS_TOKEN}, method: "POST", json: { recipient: {id: user}, message: messageData } }, function(error, response, body) { if (error) { console.log("Error sending message: ", error); } else if (response.body.error) { console.log("Error: ", response.body.error); } else { console.log("Message successfully send.") } }); } 

用它来发送回应:

 sendTextMessage(user, "Hello!"); sendTextMessage(user, "1"); sendTextMessage(user, "2"); sendTextMessage(user, "3"); 

我甚至尝试过实现一个简单的队列来排队消息,并且每次request的成功callback之后一次只发送一个消息。 这让我怀疑我没有正确地与Messenger API进行交互。

有没有人遇到过这个问题? 我怎样才能让消息顺序发送? 谢谢!

编辑

因为我实现了一个简单的队列,但是仍然遇到这个问题,所以我在这里包含了我的简单队列系统的代码。

 var queue = []; var queueProcessing = false; function queueRequest(request) { queue.push(request); if (queueProcessing) { return; } queueProcessing = true; processQueue(); } function processQueue() { if (queue.length == 0) { queueProcessing = false; return; } var currentRequest = queue.shift(); request(currentRequest, function(error, response, body) { if (error || response.body.error) { console.log("Error sending messages!"); } processQueue(); }); } queueRequest(/* Message 1 */); queueRequest(/* Message 2 */); queueRequest(/* Message 3 */); 

UPDATE

这个“bug”被报告给了Facebook,但是这听起来像是他们不会去修复它 。 请阅读Facebook上发布的post,了解他们所说的内容。 (感谢Louise为此获得Facebook的关注)

我向Facebook提交了一个bug报告,因为我遇到了同样的问题。 他们承认这确实是一个错误,正在努力解决它: https : //developers.facebook.com/bugs/565416400306038

在发送POST到/ me / messages之后,你会收到一个包含消息ID的响应(我的开头是'mid。',也许代表消息ID?):

 { recipient_id: '1015411228555555', message_id: 'mid.1464375085492:b9606c00ca33c12345' } 

在FB Messenger API完全接收之后,您会收到一个对您的webhook(没有消息事件)的确认收到的电话:

 { sender: { id: '1015411228555555' }, recipient: { id: '566031806XXXXXX' }, delivery: { mids: [ 'mid.1464375085492:b9606c00ca33c12345' ], watermark: 1464375085604, seq: 176 } } 

我认为发货收据是确保发货的最佳方式,然后发送下一条消息。

而不是添加静态超时,我会创build一个队列数据结构。 当机器人想要发送消息时,将内容追加到队列的末尾。 在消息发布callback中,检查是否有任何消息仍在队列中,并使用recursion再次调用该函数,并相应地从队列中移除。

应按收到的顺序收到。 确保你实际上是按顺序发送它们,而不是调用asynchronous函数4次(并且不保证发送顺序)。 (我读过你testing过的,但是在我所有的testing中,如果发送顺序是有保证的,我从来没有看到过接收顺序。

将发送请求作为Promise实现,并且只有在解决了前一个消息后才发送后续消息

 const send = (userId, messageData) => { return new Promise((resolve, reject) => { request ( { url : BASE_URL + "me/messages", qs : { access_token : PAGE_ACCESS_TOKEN }, method : "POST", json : { recipient: { id : userId }, message: messageData, } }, (error, response, body) => { if (error) { console.log("Error sending message: " + response.error); return reject(response.error); } else if (response.body.error) { console.log('Response body Error: ' + response.body.error); return reject(response.body.error); } console.log("Message sent successfully to " + userId); return resolve(response); } ); }); }; 

我在应用程序中添加了一个messageId计数器,在消息处理的每一次开始时都重置为0。 然后我延迟这个数字* 100毫秒。 这样我可以添加故意的延迟以及像messageDelay += 15这样的代码

 receivedMessage(event) { messageDelay = 0; //... 

sendMessage扩展:

 function sendTextMessage(recipientId, messageText) { //... setTimeout(function() { callSendAPI(messageData); }, messageDelay++ * 100) } 

该消息不是按顺序发送的,因为该请求被asynchronous发送到Facebook,并且可以以任何顺序发送。

为了解决这个问题,你必须在接收到响应之前发送的消息时调用下一个sendTextMessage

基于@ user3884594提出的recursion解决scheme,我使用它(我删除error handling,以简化):

 send_messages (["message 01", "message 02", "message 03"]); function send_messages (which, i = 0) { request({ url: 'https://graph.facebook.com/v2.10/me/messages', qs: { access_token: FACEBOOK_ACCESS_TOKEN }, method: 'POST', json: { recipient: { id: senderId }, message: { text: which [i] } }, (error, response, body) => { // You need to put your error handling logic here if (i++ < which.length - 1) send_messages (which, i); }); } 

你可以尝试把它们放在一个setTimeout函数中,这样每个函数都会在一段时间之后。

所以replace这个:

 sendTextMessage(user, "Hello!"); sendTextMessage(user, "1"); sendTextMessage(user, "2"); sendTextMessage(user, "3"); 

有了这个:

 sendTextMessage(user, "Hello!"); // 1 second setTimeout(function() { sendTextMessage(user, "1"); }, 1000) // 2 seconds setTimeout(function() { sendTextMessage(user, "2"); }, 2000) // 3 seconds setTimeout(function() { sendTextMessage(user, "3"); }, 3000) 

他们应该一个接一个地去。 如果需要的话,你也可以把函数embedded到对方中。