.then 语句不按顺序执行

.then statements not executing sequentially

我有一个使用 Node.js/Express 的应用程序。在此代码中,我有以下承诺,旨在检查我的 (PostGres) 数据库中是否已存在电子邮件:

//queries.js

const checkEmail = function(mail) {

 return new Promise(function(resolve, reject) {

  pool.query('SELECT * FROM clients WHERE email = ', [mail], function(error, results) {
   if (error) {
   reject(new Error('Client email NOT LOCATED in database!'));     
   } else {
   resolve(results.rows[0]);
   }
  })  //pool.query

 });  //new promise 
}

在我的 'main (server.js)' 脚本文件中,我有一个在提交 'signup' 表单时调用的路由。当处理此路由的 post 时...我 运行 上面的脚本检查传递的电子邮件地址是否已经位于数据库中,以及其他各种 'hashing' 例程:

我的代码如下:

//server.js

const db = require('./queries');
const traffic = require('./traffic'); 
const shortid = require('shortid');

...

app.post('/_join_up', function(req, res) {

 if (!req.body) {
 console.log('ERROR: req.body has NOT been returned...');
 return res.sendStatus(400)
 }


var newHash, newName;
var client = req.body.client_email;
var creds = req.body.client_pword;
var newToken = shortid.generate();
var firstname = req.body.client_alias; 


 db.sanitation(client, creds, firstname).then(
  function(direction) {
    console.log('USER-SUPPLIED DATA HAS PASSED INSPECTION');
  }
 ).then(
 db.checkEmail(client).then(
  function(foundUser) {
    console.log('HEY THERE IS ALREADY A USER WITH THAT EMAIL!', foundUser);
  }, 
  function(error) {
    console.log('USER EMAIL NOT CURRENTLY IN DATABASE...THEREFORE IT IS OK...');
  }
 )).then(
 traffic.hashPassword(creds).then(
  function(hashedPassword) {
    console.log('PASSWORD HASHED');
    newHash = hashedPassword;
  }, 
  function(error) {
    console.log('UNABLE TO HASH PASSWORD...' + error);
  }
 )).then(
 traffic.hashUsername(firstname).then(
  function(hashedName) {
    console.log('NAME HASHED');
    newName = hashedName;
  }, 
  function(error) {
    console.log('UNABLE TO HASH NAME...' + error);
  }
 )).then(
 db.createUser(client, newName, newHash, newToken).then(
  function(data) {
  console.log('REGISTERED A NEW CLIENT JOIN...!!!');
    
  res.redirect('/landing');  //route to 'landing' page...
  }, 
  function(error) {
    console.log('UNABLE TO CREATE NEW USER...' + error);
  }
 ))
 .catch(function(error) {
 console.log('THERE WAS AN ERROR IN THE SEQUENTIAL PROCESSING OF THE USER-SUPPLIED INFORMATION...' + error);
 res.redirect('/');  
 });

});  //POST '_join_up' is used to register NEW clients...

我的问题是“.then”语句没有按顺序出现在 运行 中。我的印象是这样的命令只有 运行 一个接一个……每个 运行 仅当前一个命令完成时。这是基于显示 'console.log' 语句读数的日志:

USER-SUPPLIED DATA HAS PASSED INSPECTION
PASSWORD HASHED
NAME HASHED
UNABLE TO CREATE NEW USER...Error: Unable to create new CLIENT JOIN!
USER EMAIL NOT CURRENTLY IN DATABASE...THEREFORE IT IS OK...

如前所述,我的印象是“.then”语句应该 运行 同步,因此最后一个语句(“用户电子邮件当前不在数据库中...因此可以... ") 实际上应该在第一个之后...根据 '.then' 语句的布局在“PASSWORD HASHED”之前。这是正常行为吗...还是我的代码有错误?

对于我的困惑,我深表歉意,但我发现“.then”语句和承诺出于某种原因有些令人困惑。我先谢谢你了。

TLDR - 您必须将 函数引用 传递给 .then(),以便 promise 基础结构稍后可以调用该函数。您在代码中的多个地方都没有这样做。

您的代码中的一个更具体的示例:

你有几个这样的结构:

.then(db.createUser().then())

这是不正确的。这告诉解释器 运行 db.createUser() 立即 并将其 return 结果(承诺)传递给.then().then() 将完全忽略你传递的任何不是函数引用的内容,你的承诺将不会被正确链接。

相反,您必须将函数引用传递给 .then(),就像这样(不确定您真正想要的执行逻辑):

.then(() => { return db.createUser.then()})

那么这里的要点是,如果你要对异步操作进行排序,那么你必须链接它们的承诺,这意味着你不能执行第二个,直到第一个调用你传递给 .then() 的函数。您没有将函数传递给 .then(),而是立即执行一个函数,然后将承诺传递给 .then(p).then() 完全忽略了该承诺,并且您的函数在父承诺之前执行已解决。


仅供参考,对一堆异步操作进行排序(看起来您正在尝试在此处执行)可以利用 await 而不是 .then() 并最终得到看起来更简单的代码。