0

I am new to Javascript and having trouble understanding how to make my functions run after one another. I want to use Promise to achieve this.

I am following Facebook Messenger tutorial to make a chat bot. Basically, I want to send messages one after another.

If I call the following lines:

sendTextMessage(recipientID, "1");
sendTextMessage(recipientID, "2");
sendTextMessage(recipientID, "3");
sendTextMessage(recipientID, "4");
sendTextMessage(recipientID, "5");

I want the message "1" to be sent first. Then, "2", "3" and so on. (instead of being sent in random order, which is the problem here.)


Here are the relevant helper functions.

function sendTextMessage(recipientId, messageText) {
  var messageData = {
    recipient: {
      id: recipientId
    },
    message: {
      text: messageText
    }
  };

  callSendAPI(messageData);
}

Here is callSendAPI function.

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

  }, function (error, response, body) {
    if (!error && response.statusCode == 200) {
      var recipientId = body.recipient_id;
      var messageId = body.message_id;

      if (messageId) {
        console.log("Successfully sent message with id %s to recipient %s", 
          messageId, recipientId);
      } else {
      console.log("Successfully called Send API for recipient %s", 
        recipientId);
      }
    } else {
      console.error("Failed calling Send API", response.statusCode, response.statusMessage, body.error);
    }
  });  
}

I have been stuck for a while. Any help would be greatly appreciated.

I tried this, but it didn't work. =(

sendTextMessage(recipientID, "1")
.then(sendTextMessage(recipientID, "2"))
.then(sendTextMessage(recipientID, "3"));
jfriend00
  • 683,504
  • 96
  • 985
  • 979
Thawsitt
  • 3
  • 2

2 Answers2

2

In your example, there is no promise, that is why it is not working. request package is not promise compatible but you can install request-promise which is a wrapper for request with bluebird.

Assuming, you are using request-promise your example would look like this :

function callSendAPI(messageData) {
  // return the promise so you can use the promise where you call the function
  return request({
    uri: 'https://graph.facebook.com/v2.6/me/messages',
    qs: { access_token: PAGE_ACCESS_TOKEN },
    method: 'POST',
    json: messageData
      }).then( function(body) {
      var recipientId = body.recipient_id;
      var messageId = body.message_id;

      if (messageId) {
        console.log("Successfully sent message with id %s to recipient %s", 
          messageId, recipientId);
      } else {
      console.log("Successfully called Send API for recipient %s", 
        recipientId);
      }
    }).catch(function(error) {
      console.error("Failed calling Send API", response.statusCode, response.statusMessage, body.error);
    });
}

And for the other function :

function sendTextMessage(recipientId, messageText) {
  var messageData = {
    recipient: {
      id: recipientId
    },
    message: {
      text: messageText
    }
  };

  return callSendAPI(messageData);
}

Notice that you have to return the promise otherwise it is not usable by the line calling the function.

clementescolano
  • 485
  • 5
  • 15
2

To make this work, make your two helper functions return promises. So in callSendAPI you create and return one, and sendTextMessage should just return that same promise it gets from callSendAPI. Finally, make sure to pass functions to your then calls, instead of executing a function. You can use .bind() to create a new function from an existing one and specify the arguments that should be passed when called.

function callSendAPI(messageData) {
    return new Promise(function (resolve, reject) { // ***
        request({
            uri: 'https://graph.facebook.com/v2.6/me/messages',
            qs: { access_token: PAGE_ACCESS_TOKEN },
            method: 'POST',
            json: messageData
        }, function (error, response, body) {
            if (!error && response.statusCode == 200) {
                var recipientId = body.recipient_id;
                var messageId = body.message_id;
                if (messageId) {
                    console.log("Successfully sent message with id %s to recipient %s", 
                                messageId, recipientId);
                } else {
                    console.log("Successfully called Send API for recipient %s", 
                                recipientId);
                }
                resolve(body); // ***
            } else {
                console.error("Failed calling Send API", response.statusCode,
                              response.statusMessage, body.error);
                reject(body.error); // ***
            }
        });
    });
}

function sendTextMessage(recipientId, messageText) {
    var messageData = {
        recipient: {
            id: recipientId
        },
        message: {
            text: messageText
        }
    };
    return callSendAPI(messageData); // *** returns promise
}

sendTextMessage(recipientID, "1")
.then(sendTextMessage.bind(null, recipientID, "2")) // *** pass a function reference
.then(sendTextMessage.bind(null, recipientID, "3"))
.catch(function (body) {
     console.log('aborted');
});
trincot
  • 317,000
  • 35
  • 244
  • 286