Function returning before async method done Node J

2019-02-26 10:55发布

I currently have a function that is called from my router:

router.js:

var result = Api.getUser();

console.log("Result: " + result);

api.js

exports.getUser = function(req, result) {

    request.get({
        uri: URL + '/user/me/',
        headers: {Authorization: 'bearer ' + req.user.accessToken},
        json: true
      }, function(e, r, body) {

        console.log("e: " + e + " body: %j", body);

            if(e) {

                return "{error: true}";

            } else {

                return body;

            }

    });

};

The problem I am having is that I am getting the log "Result: undefined" first.

Is there a way to hold the function getUser from returning until the function for get finishes?

3条回答
劫难
2楼-- · 2019-02-26 11:25

You are dealing with asynchronous code. There are a couple ways to solve this problem.

With A Promise

// api.js
var Promise = require('bluebird');
var request = require('request');
var getP = Promise.promisify(request.get.bind(request));

exports.getUser = function(accessToken) {
  return getP({
    uri: URL + '/user/me/',
    headers: {Authorization: 'bearer ' + accessToken},
    json: true
  }).spread(function(e, r, body) {
    console.log("e: " + e + " body: %j", body);
    if(e) {
      return Promise.reject("{error: true}");
    } else {
      return Promise.resolve(body);
    }
  });
};

// main.js
api.getUser(req.user.accessToken)
  .then(console.log.bind(console, "Result: "))
  .catch(console.error.bind(console));

With A Callback

// api.js
var request = require('request');

exports.getUser = function(accessToken, callback) {
  request.get({
    uri: URL + '/user/me/',
    headers: {Authorization: 'bearer ' + accessToken},
    json: true
  }, function(e, r, body) {
    console.log("e: " + e + " body: %j", body);
    if(e) {
      callback("{error: true}");
    } else {
      callback(null, body);
    }
  });
};

// main.js
api.getUser(req.user.accessToken, function (err, result) {
  if (err) return console.error(err);
  console.log("Result: " + result);
});

The nice thing about the promise API is that you only ever need to check for errors once, in your final .catch handler. In the callback style if you need to keep making additional asynchronous calls then you'll have to keep nesting callbacks and checking if (err) return console.error(err) in every single callback.

查看更多
劳资没心,怎么记你
3楼-- · 2019-02-26 11:26

You can't return from an async function, you use a callback:

exports.getUser = function(req, result, callback) {
   request.get({
    uri: URL + '/user/me/',
    headers: {Authorization: 'bearer ' + req.user.accessToken},
    json: true
  }, function(e, r, body) {
        if(e) {
            callback({error: true});
        } else {
            callback(body);
        }
    });
};

Api.getUser(req, result, function(user) {
    console.log(user);
});
查看更多
Rolldiameter
4楼-- · 2019-02-26 11:35

Promises are awesome, I would suggest looking into them. However, a simple callback will do the trick

api:

exports.getUser = function(req, result, callback) {
  request.get({
    uri: URL + '/user/me/',
    headers: {Authorization: 'bearer ' + req.user.accessToken},
    json: true
  }, function(e, r, body) {
        if(e) {
            callback({error: true});
        } else {
            callback(body)
        }
    });
};

router:

var result
Api.getUser(req, result, function (response) {
  result = response
  console.log(result)
});
查看更多
登录 后发表回答