繁体   English   中英

链接ES6承诺没有嵌套

[英]Chaining ES6 promises without nesting

我试图在第一个之后链接第二个然后方法,但由于某种原因它不能正常工作。 它只在我嵌套then方法时才能正常工作。 这是无法正常工作的代码:

auth.post('/signup', (req, res, next) => {

  const { username } = req.body
  const { password } = req.body

  Users.findOne({ username })
    .then(
      existingUser => {
        if (existingUser) return res.status(422).send({ error: 'Username is in use' })

        const user = new Users({ username, password })
        user.save()
      },
      err => next(err)
    )
    .then(
      savedUser => res.send({ 
        username: savedUser.username, 
        password: savedUser.password 
      }),
      err => next(err)
    )
})

这里当我发布到'/signup' user被保存到数据库中但我没有得到用户名和密码的响应。 然而:

auth.post('/signup', (req, res, next) => {

  const { username } = req.body
  const { password } = req.body

  Users.findOne({ username })
    .then(
      existingUser => {
        if (existingUser) return res.status(422).send({ error: 'Username is in use' })

        const user = new Users({ username, password })
        user.save()
        .then(
          savedUser => res.json({ 
            username: savedUser.username,
            password: savedUser.password
          }),
          err => next(err)
        )
      },
      err => next(err)
    )
})

这按预期工作。 user得到保存,我得到用户名和密码的响应。 我已经读过你可以在没有嵌套的情况下以平面方式链接这些方法。 但我在这里检查了一些问题,无法找到答案,我在这里做错了什么。 有人可以帮忙解决这个问题吗?

简单的3步过程:

  1. 从第一个.then电话返回一个承诺

改变这个:

// ...
const user = new Users({ username, password })
user.save()
// ...

对此:

// ...
const user = new Users({ username, password })
return user.save()
// ...

(注意return关键字,它将使用第二个.then()调用链接它)


2.如果existingUser返回false 拒绝Promise (感谢@JaromandaX指出)

改变这个:

if (existingUser) return res.status(422).send({ error: 'Username is in use' })

对此:

if (existingUser) {
    res.status(422).send({ error: 'Username is in use' });
    return Promise.reject('USER_EXISTS');
}

3.尽可能删除.then(onResolvedFunction, onRejectedFunction)模式 ,并使用.catch(err)代替(以捕获更大范围的错误)。

.then()删除第二个参数

,
err => next(err)

使用.catch代替:

Users.findOne({ username })
    .then(...)
    .then(...)
    .catch((e) => { // <-- Handle the error properly
         console.log(e);
         if (e !== 'USER_EXISTS')
             next(err);
     }); 

猫鼬脚注!

这与承诺无关。 我看到你为你的模型Users命名,但请记住,在内部,Mongoose会为你复制你的模型名称。 你应该:

  • 为您的模型命名User ; 要么
  • 在第三个参数中明确设置复数形式,如下所示:

    const Users = mongoose.model('User', UserSchema, 'Users');

您的“链式”版本至少有三个问题

  1. 你是不是从你的第一个返回任何东西.then
  2. 在现有用户的情况下,链式.then仍将被执行
  3. 在在拒绝的情况下Users.findOne链式.then也将被执行

修理:

  1. 只需返回.save()
  2. 返回一个Promise.reject - 或者你可以throw一个错误
  3. 不使用onRejected的功能.then ,只是有一个单一的拒绝处理程序,在链的末端,在.catch

我会链接这样的代码:

auth.post('/signup', (req, res, next) => {

    const { username } = req.body
    const { password } = req.body

    Users.findOne({ username })
    .then(existingUser => {
        if (existingUser) {
            return Promise.reject({
                status:422,
                error: 'Username is in use' 
            });
        }
        return new Users({ username, password }).save();
    })
    .then(savedUser => res.send({ 
        username: savedUser.username, 
        password: savedUser.password 
    }))
    .catch(err => {
        if (err.status) {
            return res.status(err.status).send({ error: err.error });
        }
        return next(err);
    });
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM