Returning a string value from a promise

Russell Christopher picture Russell Christopher · May 29, 2014 · Viewed 11.5k times · Source

In the code below, you see me making an HTTP request. I parse the response and pull out and a "token" (a string) . I want to return that token so that its value is assigned to foo.

foo = request.post(
        {
            url: 'http://10.211.55.4/api/2.0/auth/signin',
            body: reqLogin.toString(),
            headers: {'Content-Type': 'text/xml'}
        },
        function(err, response, body) {
            if(err) {
                console.log(err);
                process.exit(1);
            } 
            else {
                parseString(body, function (err, result) {
                    tokencontainer = (result.tsResponse.credentials[0]);
                    token = tokencontainer.$.token;
                    console.log('Logged in, token is ', token);
                    return token;
                });
            }           
        }
    );

When I run this code, the object type of foo is Request. Can I somehow cast the whole request to "string" so I don't get the request object assigned to foo? I simply want the "token" value assigned to the variable.

Thanks!

Answer

kamituel picture kamituel · May 29, 2014

If you're using Mikeal's request library, .post() method (or any other) does not return a promise (and even if it did, you wouldn't be able to assign a value this way (rather a promise).

So, your options are:

  1. move your logic which uses "foo" to a separate function and call it form a callback.
  2. wrap .post() in a promise using one of helper libraries (like Q).
  3. find anotehr HTTP library which will support promises.

(note: I wrote the code above but have not ran it, so it might not work as-it-is. But it gives you an idea)

Option 1 could look like:

var logicUsingFoo = function(foo) {
  // do stuff with foo here
};

request.post({...}, function (err, response, body) {
  // ...
  logicUsingFoo(token);
});

// Here, you can't really use foo, because request.post() has not yet
// finished. In Javascript, there's no way to pause program execution.
// You need to either use callbacks, or promises.

Option 2

Something like (using Q library):

var promisePost = function(params) {
    var q = Q.defer();

    request.post(params, function(err, response, body) {
      if (err) {
          q.reject(err);
      } else {
          q.resolve(body);
      }
    };

    return q.promise;
}

Then use it:

promisePost({url: ..., headers: ...}).then(function (body) {
  // Do stuff with body, obtain token etc.
}, function (err) {
  // Handle error
});

Option 3

You could use, for instance, Q-IO by Kris Kowal, the same guy who created widely used Q library for promises.