首页 > 解决方案 > 为什么我的承诺没有正确解决?

问题描述

exports.addUser = async(req, res) => {
  const {
    username,
    email,
    password
  } = req.body;
  //hash password
  const password_hash = await hashPassword(password);
  //check whitelist
  this.checkWhitelist(email).then(function(response) {
    if (response) {
      console.log("RESOLVED TRUE")
      //POST user to Airtable
      new Promise(function(resolve, reject) {
        return usersTable.create({
            email,
            username,
            password_hash,
            "email_verified": "false"
          },
          function(err) {
            if (err) {
              resolve(false);
              console.error(err);
              res.send({
                "Success": false,
                "responseCode": 502,
              })
            }
            resolve(true);
            res.send({
              "Success": true,
              "responseCode": 200,
            });
          }
        ).then(function(response) {
          if (response) {
            const EMAIL_SECRET = "xxxxxxxxxxx";
            jwt.sign({
                'username': username,
              },
              EMAIL_SECRET, {
                expiresIn: '1d',
              },
              (err, emailToken) => {
                const url = `http://localhost:3000/confirmation/${emailToken}`;

                transporter.sendMail({
                  to: args.email,
                  subject: 'Confirm Email',
                  html: `Please click this email to confirm your email: <a href="${url}">${url}</a>`,
                });
              }
            )
          }
        })
      })
    } else {
      console.log('RESOLVED FALSE')
      res.send({
        "Success": false,
        "responseCode": 403
      })
    }
  })
}

出于某种原因,我创建的承诺usersTable.create没有正确解决。当我打电话.then()后,我收到错误:UnhandledPromiseRejectionWarning:TypeError:无法读取未定义的属性'then'。

就上下文而言,这是一个 webapp 的用户注册流程。首先,对通行证进行哈希处理,然后根据白名单检查电子邮件(到目前为止,这个逻辑是有效的)。现在我只需要验证电子邮件,但无法.then()正确调用。

这是怎么回事?

标签: javascriptnode.jsasynchronous

解决方案


在你的第一个thenreturn createTable需要的地方,return new Promise所以它可以链接到下一个then

如果createTable返回一个承诺,您可以简单地编写return createTable并摆脱new Promise包装它的内容。

由于您async-await在代码的早期使用,我建议您完全移至该代码,因为它使代码更易于阅读。

对此,我进行了一次尝试,

exports.addUser = async(req, res) => {
  const {
    username,
    email,
    password
  } = req.body;
  //hash password
  const password_hash = await hashPassword(password);
  //check whitelist
  try {
    const whitelist = await this.checkWhiteList(email)
    if (whitelist) {
      await usersTable.create() // shortened for readability sake.
      const EMAIL_SECRET = 'xxxxxxxxxxx';
      jwt.sign(
        {
          'username': username,
        },
        EMAIL_SECRET,
        {
          expiresIn: '1d',
        },
        (err, emailToken) => {
          const url = `http://localhost:3000/confirmation/${emailToken}`;

          transporter.sendMail({
            to: args.email,
            subject: 'Confirm Email',
            html: `Please click this email to confirm your email: <a href="${url}">${url}</a>`,
          });
        }
      );
    }
    res.send({
      'Success': true,
      'responseCode': 200,
    });
  } catch (error) {
    res.send({
      'Success': false,
      'responseCode': 403,
    });
  }
}

推荐阅读