【问题标题】:NodeJS responds before function is doneNodeJS 在函数完成之前响应
【发布时间】:2017-09-30 03:57:19
【问题描述】:

我正在为一个学校项目使用 NodeJS 和 Express 编写 API,但我正在努力解决以下问题:

getAuthUserId 函数解码 JWT 令牌并从 mongoDB 服务器中的用户获取 Id。

我在 REST 调用“/user/authTest”中调用此函数。但是当我调用这个时,服务器在数据库可以返回 Id 之前做出响应,并且变量 UId 是未定义的。如您所见,实际上找到了 Id。关于如何解决此问题的任何想法?

API调用代码:

apiRoutes.post('/user/authTestID', function(req, res) {
  var UId = getAuthUserId(req, res);
  console.log(UId);
  if (UId) {
    res.sendStatus(200);
  }else{
    res.sendStatus(400);
  }

}); 

功能:

function getAuthUserId(req, res) {
    var user = new User();
  var token = user.getToken(req.headers);
  if (token) {
    var decoded = jwt.decode(token, config.secret);
    User.findOne({
      name: decoded.name
    }, function(err, user) {
        if (err) throw err;

        if (!user) {
          res.status(403).send({success: false, msg: 'Authentication failed. User not found.'});
          return false
        } else {
          console.log('Auth for ' + user.name + ' ' + user._id);
          return user._id
        }
    });
  } else {
    res.status(403).send({success: false, msg: 'No token provided.'});
    return '';
  }
}

终端的输出:

[nodemon] restarting due to changes...
[nodemon] starting `node server.js`
Connected to MongoDB
undefined
::ffff:192.168.0.111 - POST /user/authTestID HTTP/1.1 400 11 - 175.006 ms
Auth for test 58f8954c3602b80552b6f1fb

提前致谢!

【问题讨论】:

标签: javascript node.js rest express mongoose


【解决方案1】:

你需要像这样做出承诺。

API

apiRoutes.post('/user/authTestID', function(req, res) {
  getAuthUserId(req, res).then(function (UId) => {
    console.log(UId);

    if (UId) {
      res.sendStatus(200);
    }else{
      res.sendStatus(400);
    }
  });

}, function(err) {
    console.log(err.msg)
    res.status(err.status).send(err.msg);
});

功能

function getAuthUserId(req, res) {
    return new Promise(function(resolve, reject){
        var user = new User();
        var token = user.getToken(req.headers);
        if (token) {
            var decoded = jwt.decode(token, config.secret);
            User.findOne({
                name: decoded.name
            }, function(err, user) {
                if (err) throw err;

                if (!user) {
                    reject({status: 403, msg: 'Authentication failed. User not found.'});
                } else {
                    console.log('Auth for ' + user.name + ' ' + user._id);
                    resolve(user._id)
                }
            });
        } else {
            reject({status: 403, msg: 'No token provided.'});
        }
    })
}

【讨论】:

  • 完美!非常感谢!
【解决方案2】:

getAuthUserId 获取 CALLBACK !!! 中的值。您不能指望它从中返回值。您可以尽快执行以下操作。

        apiRoutes.post('/user/authTestID', function (req, res) {
            var user = new User();
            var token = user.getToken(req.headers);
            if (token) {
                var decoded = jwt.decode(token, config.secret);
                User.findOne({
                    name: decoded.name
                }, function (err, user) {
                    if (err) throw err;
                    if (!user) {
                        return res.status(403).send({success: false, msg: 'Authentication failed. User not found.'});
                    } else {
                        console.log('Auth for ' + user.name + ' ' + user._id);
                        return res.send(user._id)
                    }
                });
            } else {
                return res.status(403).send({success: false, msg: 'No token provided.'});
                // return '';
            }
        });

尝试使用 Promise 库,例如 Bluebird

【讨论】:

  • 感谢您的建议!我已经阅读了有关 Promise 的内容,但我不知道在这种情况下可以使用它们!
【解决方案3】:

James 的评论看起来是关于异步调用的一个很好的、详尽的资源。正如其他人所提到的,您不能在回调中返回值。您可以使用 Promise 库,或者您可以更改 getAuthUserId 函数以进行回调并在其中包含您的 console.log 逻辑:

例子:

API调用代码:

apiRoutes.post('/user/authTestID', function(req, res) {
  getAuthUserId(req, res, function(UId) {
  // we're in a your new callback
  console.log(UId);
  if (UId) {
    res.sendStatus(200);
  }else{
    res.sendStatus(400);
  }
  });
});

功能代码

// note new callback param
function getAuthUserId(req, res, callback) {
  var user = new User();
  var token = user.getToken(req.headers);
  if (token) {
    var decoded = jwt.decode(token, config.secret);
    User.findOne({
      name: decoded.name
    }, function(err, user) {
        if (err) throw err;

        if (!user) {
          res.status(403).send({success: false, msg: 'Authentication failed. User not found.'});
          callback(false) // no more return, call callback with value
        } else {
          console.log('Auth for ' + user.name + ' ' + user._id);
          callback(user._id) // no more return, call callback with value
        }
    });
  } else {
    res.status(403).send({success: false, msg: 'No token provided.'});
    callback(''); // no more return, call callback with value
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-16
    • 1970-01-01
    • 1970-01-01
    • 2016-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多