0

I'm trying to make a chained request on some API with javascript Promises. On the first function i query the data and i get one ID and return it. On the second function, i get the ID of the first function, i query more data and on the 3rd function i send them to my API. And my code is the following.

var express = require("express");
var app = express();
var FB = require("fb");
var request = require("request");
var Promise = require("promise");
var eventData = {};
var venueId, theUrl;

app.get("/writeEvents", function(req, res) {
  Promise.resolve(1)
    .then(() => {
      return Promise.resolve(req.query.eventID);
    })
    .then(value => {
      FB.options({ version: "v2.10" });
      FB.setAccessToken("sometoken");
      FB.api("" + value + "", { fields: eventFields }, function(results) {
        if (!results || results.error) {
          console.log(!results ? "error occurred" : results.error);
          return;
        }
        venueId = results.owner.id;
        console.log("first: " + venueId);
        //res.send(JSON.stringify(results, null, "    "));
        /*EVENT*/
        eventData["id"] = results.id;
        eventData["name"] = results.name;
      });
      return Promise.resolve(venueId);
    })
    .then(value => {
      FB.options({ version: "v2.10" });
      FB.setAccessToken("sometoken");
      console.log("second: " + value);
      FB.api("" + value + "", { fields: pageFields }, function(resPage) {
        if (!resPage || resPage.error) {
          console.log(!resPage ? "error occurred" : resPage.error);
          return;
        }

        /*VENUE*/
        eventData["venue"] = {};
        eventData["venue"]["id"] = resPage.id;
        eventData["venue"]["name"] = resPage.name;
      });
      return true;
    })
    .then(value => {
      var toJson = JSON.stringify(eventData, null, "    ");
      var parametrus = encodeURIComponent(toJson);
      theUrl = "https://example2.com?eventData=" + parametrus + "";
      res.send(
        JSON.stringify(eventData, null, "    ") + " the url : " + theUrl
      );
      request(theUrl, function(error, response, body) {
        console.log("error:", error); // Print the error if one occurred
        console.log("statusCode:", response && response.statusCode); // Print the response status code if a response was received
        console.log("body:", body); // Print the HTML for the Google homepage.
      });
      return Promise.resolve();
    })
    .catch(error => {
      console.log(error);
    });
});
app.listen(port);

And when i hit in my browser the example.com/writeEvents?eventID=1906888876040770

I get the following printed on screen

{} the url : https://example2.com/writeEventsTwo?eventData=%7B%7D

And in console

enter image description here

As you can see... The second print is being fired before the first one ! Any idea of why it fails?

Asad Saeeduddin
  • 46,193
  • 6
  • 90
  • 139
Konstantinos Natsios
  • 2,874
  • 9
  • 39
  • 74
  • 3
    `return Promise.resolve(venueId);` ... returns this resolved promise immediately, it doesn't magically wait for the asynchronous code before it to complete ... also, there's almost never a need to return a "Promise.resolve" in a .then, .then promisifies the return value for you – Jaromanda X Nov 19 '17 at 23:04
  • note: `Promise.resolve(1) .then(() => { return Promise.resolve(req.query.eventID); })` is all redundant code – Jaromanda X Nov 19 '17 at 23:05
  • In other words return the promise but resolve it in the FB.api callback when you have a `venueid` – charlietfl Nov 19 '17 at 23:06
  • @JaromandaX i thought that until the FB.api finishes, it will not go to the return part. – Konstantinos Natsios Nov 19 '17 at 23:09
  • @KwnstantinosNatsios - **if** it's asynchronous, then, no – Jaromanda X Nov 19 '17 at 23:11
  • The name `resolve` might be confusing you here. It doesn't resolve some future value into the present. In fact it does just the conceptual opposite: it takes some value that is available to you now and wraps it into a promise (which represent deferred values). – Asad Saeeduddin Nov 19 '17 at 23:13
  • @AsadSaeeduddin yes, actually i thought that the return part is when everything before has finished. Could you write me an example for resolving the FB.api ? – Konstantinos Natsios Nov 19 '17 at 23:14
  • It seems that `FB.api` accepts a callback. In order to wrap callback based APIs into a Promise based API, one approach is to use the promise constructor: `new Promise(resolve => setTimeout(() => resolve("foo"), 1000))` is a promise that will be fulfilled with the value "foo" after 1 second. – Asad Saeeduddin Nov 19 '17 at 23:17

0 Answers0