尝试编写一个函数来使用回调来发送Facebook Messenger消息

时间:2018-04-04 19:59:48

标签: node.js loops callback

我试图编写一个函数来使用回调来在Facebook Messenger中发送消息。我需要这样做,因为我在从数组发送文本时遇到问题。邮件将被发送,但顺序不正确。我认为这是因为Nodejs比传输文本更快地循环元素。请参阅我关于此here的问题。

所以现在我正在尝试使用回调重写我的发送函数,徒劳地希望我能以某种方式强迫NodeJS在跳转到下一个元素之前实际等待!

到目前为止,我有以下代码:

Main send function:

sendWithCallback: function(messageData, callback) {
    request({
            uri: 'https://graph.facebook.com/v2.6/me/messages',
            qs: {
                access_token: config.FB_PAGE_TOKEN
            },
            method: 'POST',
            json: messageData

        }, function (error, response, body) {
            if (!error && response.statusCode === 200) {
                let recipientId = body.recipient_id;
                console.log("Message sent to recipient '%s'", recipientId);
                callback(true);
            } else {
                console.error("Could not send message: ", response.statusCode, response.statusMessage, body.error)
                callback(false);
            }
        }
    );
},

Function for sending a "multi part" message (i.e. an Array of text):

sendMultipartMessage: function(recipientId, textArray) {
    let messageData, msgPart, msgLength, count = 0;
    msgLength = textArray.length;
    while (count < msgLength) {
        msgPart = textArray[count];
        messageData = {
            recipient: {
                id: recipientId
            },
            message: {
                text: msgPart
            }
        };
    }
    self.sendWithCallback(messageData, function(sent) {
        if (sent) {
            count++;
            console.log("Message part %s sent.", msgPart);
        }
        else {
            console.log("Couldn't send message");
        }
    });
},

在我的脑海中,这段代码正常运行!它发送文本(从数组中获取),然后递增计数,直到它等于messageLength。但实际上,DOESN&#T; T会这样做。相反,它只是进入一个无限循环(我无法在我的日志中看到)然后崩溃应用程序。

我做错了什么?

1 个答案:

答案 0 :(得分:0)

如果我们简化你的循环,它基本上就变成了这个:

let count = 0;
while (count < msgLength) {
  messageData = data;
}

你永远不会增加数量。

我认为您打算移动while循环中的self.sendWithCallback调用 。然而,这仍然不会做你想要的,并将永远运行。即使它确实按照您的意愿行事,也无法解决按顺序发送消息的问题。

JavaScript's concurrency model使用带有&#34;运行到完成的事件循环。&#34;您可以使用request调用sendWithCallback之类的内容将消息传递到事件队列。这只会向队列添加一条消息,但在当前正在运行的块完成之前不会处理该消息。这意味着你的while循环实际上必须在你的任何请求开始运行之前完成。我们可以使用setTimeout构建一个更简单的示例:

let count = 0;
while (count < 1) {
  setTimeout(() => {
    count++;
  }, 1000);
}
console.log('while loop completed');

在上面,while循环永远不会完成,因为count永远不会在同一个块中递增(console.log永远不会被调用)。它需要先完成,然后才能开始使用setTimeout处理正在创建的异步消息。

你实际上可以像这样重写它:

textArray.forEach(msgPart => self.sendWithCallback(msgPart, sent => {
  if (!sent) console.error('Could not send message');
});

但是,这并不能保证消息的发送顺序,即使其中一条消息触发了错误,它也会发送消息。如果要按顺序发送它们,则必须在回调中递归调用sendWithCallback,以便在上一个消息完成后再显示下一条消息。这可能看起来像这样:

let count = 0;
const sendMessage = (textArray, count) => {
  self.sendMessageWithCallback(textArray[count], sent => {
    count++;
    if (sent && count < textArray.length) {
      sendMessages(textArray, count);
    }
  });
}
sendMessages(textArray, 0);

如果您使用的是承诺和async / await,您可以更简单地将其写为:

for (count = 0; count < msgLength; count++) {
  await self.sendMessageAsync(textArray[count]);
}

然而,这需要对周围代码进行更大的重写,并使用诸如请求承诺之类的东西,而不仅仅是请求。