链接ES6承诺没有嵌套

时间:2017-08-04 10:05:33

标签: javascript ecmascript-6 es6-promise

我试图在第一个方法之后连接第二个方法,但由于某种原因它无法正常工作。它只在我嵌套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被保存,我收到了用户名和密码的回复。我已经读过你可以在没有嵌套的情况下以平面方式链接这些方法。但是我已经在这里查了一些问题,而且无法找到我在这里做错的答案。有人可以帮忙解决这个问题吗?

2 个答案:

答案 0 :(得分:2)

简单的3步骤过程:

  1. 从第一次.then电话返回承诺。
  2. 改变这个:

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

    到此:

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

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

    <强> 2。拒绝承诺以防existingUser返回false(感谢@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(错误)(以捕获更大范围的错误)。

    .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 :(得分:1)

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

  1. 您没有从第一个AnotherComponent{id:ModelData}
  2. 返回任何内容
  3. 在现有用户的情况下,链式.then仍将被执行
  4. 如果在.then拒绝,则链接Users.findOne也会被执行
  5. 修复:

    1. 只需返回.then
    2. 即可
    3. 返回.save() - 您也可以Promise.reject错误
    4. 不要在throw中使用onRejected个功能,只需在链的末尾有一个拒绝处理程序,在.then
    5. 我会链接这样的代码:

      .catch