Nodejsexpression和承诺不做我期望的

我正在尝试使用NodeJS构build一个loginAPI,但是我的代码并没有达到我期望的效果。 我对js,承诺等都很陌生,所以请尽可能简化任何答案。

从我的代码输出中可以看到,第一个promise部分不会等到函数findUsers(...)完成。

我有一个路线文件,我想依次运行几个函数:

  1. 查找用户是否存在于数据库中
  2. 如果(1为真)散列并input密码
  3. …等

路线文件现在包含:

 var loginM = require('../models/login'); var loginC = require('../controllers/login'); var Promise = require('promise'); module.exports = function(app) { app.post('/login/', function(req, res, next) { var promise = new Promise(function (resolve, reject) { var rows = loginM.findUser(req.body, res); if (rows.length > 0) { console.log("Success"); resolve(rows); } else { console.log("Failed"); reject(reason); } }); promise.then(function(data) { return new Promise(function (resolve, reject) { loginC.doSomething(data); if (success) { console.log("Success 2"); resolve(data); } else { console.log("Failed 2"); reject(reason); } }); }, function (reason) { console.log("error handler second"); }); }); } 

findUser函数包含池和查询,并位于模型文件中:

 var connection = require('../dbConnection'); var loginC = require('../controllers/login'); function Login() { var me = this; var pool = connection.getPool(); me.findUser = function(params, res) { var username = params.username; pool.getConnection(function (err, connection) { console.log("Connection "); if (err) { console.log("ERROR 1 "); res.send({"code": 100, "status": "Error in connection database"}); return; } connection.query('select Id, Name, Password from Users ' + 'where Users.Name = ?', [username], function (err, rows) { connection.release(); if (!err) { return rows; } else { return false; } }); //connection.on('error', function (err) { // res.send({"code": 100, "status": "Error in connection database"}); // return; //}); }); } } module.exports = new Login(); 

我得到的输出是:

 Server listening on port 3000 Something is happening error handler second Connection 

所以我想知道这个代码是双重的:

  1. 为什么第一个承诺不会在继续if / else之前等待findUser返回,那么为了发生这种情况我需要做些什么?
  2. 为什么error handler second输出,但没有Failed

我觉得有什么我完全误解了承诺。 我很感激任何答案。 谢谢。

与代码有关的问题

好的,这里有很多问题,所以首先要做的事情。

  connection.query('...', function (err, rows) { connection.release(); if (!err) { return rows; } else { return false; } }); 

这是行不通的,因为你正在向调用者返回数据,调用者是用errrows调用你的callback的数据库查询,并且不关心你的callback的返回值。

你需要做的是当你有行或者你没有时调用其他函数或方法。

你在打电话:

 var rows = loginM.findUser(req.body, res); 

你希望得到那里的行,但你不会。 你会得到什么是undefined ,你会得到它比数据库查询甚至开始更快。 它是这样工作的:

 me.findUser = function(params, res) { // (1) you save the username in a variable var username = params.username; // (2) you pass a function to getConnection method pool.getConnection(function (err, connection) { console.log("Connection "); if (err) { console.log("ERROR 1 "); res.send({"code": 100, "status": "Error in connection database"}); return; } connection.query('select Id, Name, Password from Users ' + 'where Users.Name = ?', [username], function (err, rows) { connection.release(); if (!err) { return rows; } else { return false; } }); //connection.on('error', function (err) { // res.send({"code": 100, "status": "Error in connection database"}); // return; //}); }); // (3) you end a function and implicitly return undefined } 

在连接到数据库之前,在传递函数之后, pool.getConnection方法会立即返回。 然后,在一段时间之后,您传递给该方法的函数可能会被调用,但在已经将undefined的代码返回给需要值的代码之后,

 var rows = loginM.findUser(req.body, res); 

而不是从callback中返回值,你需要调用一些其他的函数或方法(如一些你需要调用的callback函数或者一个解决承诺的方法)。

返回值是一个同步的概念,不适用于asynchronous代码。


如何承诺应该使用

现在,如果你的函数返回了一个promise

 me.findUser = function(params, res) { var username = params.username; return new Promise(function (res, rej) { pool.getConnection(function (err, connection) { console.log("Connection "); if (err) { rej('db error'); } else { connection.query('...', [username], function (err, rows) { connection.release(); if (!err) { res(rows); } else { rej('other error'); } }); }); }); } 

那么你就可以像这样在代码的其他部分使用它:

 app.post('/login/', function(req, res, next) { var promise = new Promise(function (resolve, reject) { // rows is a promise now: var rows = loginM.findUser(req.body, res); rows.then(function (rowsValue) { console.log("Success"); resolve(rowsValue); }).catch(function (err) { console.log("Failed"); reject(err); }); }); // ... 

说明

总之,如果你正在运行一个asynchronous操作 – 就像数据库查询 – 那么你不能立即得到这样的值:

 var value = query(); 

因为服务器在执行任务之前需要阻止等待数据库 – 这就是每种语言在同步,阻塞I / O时发生的情况(这就是为什么你需要在这些语言中有线程,以便其他的东西可以该线程被阻止时完成)。

在Node中,您可以使用传递给asynchronous函数的callback函数,以便在有数据时调用它:

 query(function (error, data) { if (error) { // we have error } else { // we have data } }); otherCode(); 

或者你可以得到一个承诺:

 var promise = query(); promise.then(function (data) { // we have data }).catch(function (error) { // we have error }); otherCode(); 

但是在这两种情况下,在注册callbackotherCode()或promise处理程序之后,在查询有数据之前, otherCode()将立即运行 – 这是不需要阻塞的。

概要

整个想法是,在像Node.JS这样的asynchronous,非阻塞,单线程的环境中,你一次只能做一件事 – 但是你可以等待很多事情。 但是,当你在等待的时候,你不只是等待什么,什么都不做,你安排了其他的事情,等待更多的事情,最终在你准备好的时候你会被打回去。

其实我写了一个关于中等的短篇故事来说明这个概念: 在这个星球上的非黑化I / O Asynchronia256 / 16 – 一个松散的基于不确定事实的短小故事 。