多个嵌套的Mongoose承诺的结构

时间:2017-07-28 07:50:50

标签: javascript node.js mongodb mongoose response

我如何构建一个彼此嵌套多个Mongoose.findOne()的函数?

我需要做类似

的事情
const userId  = '...';
const postId  = '...';
const imageId = '...';

User.findById(userId).then(user => {
  if (!user) {
    return res.status(400).json({
      status: 'error',
      err: 'User not found',
    });
  }

  Post.findById(postId).then(post => {
    if (!post) {
      return res.status(400).json({
        status: 'error',
        err: 'Post not found',
      });
    }

    Image.findById(imageId).then(image => {
      if (!image) {
        return res.status(400).json({
        status: 'error',
        err: 'Image not found',
      });

      // DO SOMETHING WITH VARIABLES 'user', 'post', AND 'image'

    }).catch(err => { .. });
  }).catch(err => { .. });
}).catch(err => { .. });

由于Collection.findById()返回一个承诺,我想我应该使用链接代替这种结构。

所以它可能像

User
  .findById(userId)
  .then(user => Post.findById(postId))
  .then(post => Image.findById(imageId))
  .then(image => {
      // DO SOMETHING WITH VARIABLES 'user', 'post', AND 'image'
  });
  .catch(err => { .. });

但我不知道如何访问变量userpostimage,以及如何抛出错误,因此我可以在{ {1}}陈述。

修改

我试过这个

catch

但我刚收到

async function getPostAsync() {
  const userId = '597989c668189f31483ffdbf';
  const postId = '597989c62624ea74750c74f8';

  if (!userId) {
    throw new Error('User id missing');
  }

  if (!postId) {
    throw new Error('Post id missing');
  }

  const user = await User.findById(userId);
  const post = await Post.findById(postId);

  return post;
}

app.get('/', (req, res) => {
  getPostAsync().then(post => {
    res.json({
      status: 'success',
    });
  }).catch(err => {
    res.status(400).json({
      status: 'error',
      err
    });
  })
});

我做错了吗?

但是即使用

我也能得到相同的结果
{
  "status": "error",
  "err": {}
}

所以我可能会错误地调用异步函数。

2 个答案:

答案 0 :(得分:3)

您可以使用Promise.all

Promise.all([
    User.findById(userId),
    Post.findById(postId),
    Image.findById(imageId)
])
.then(result)=>{
    let user = result[0];
    let post = result[1];
    let image = result[2];
})
.catch(err => { .. });

destructing assignment

Promise.all([
    User.findById(userId),
    Post.findById(postId),
    Image.findById(imageId)
])
.then(([user, post, image])=>{...})
.catch(err => { .. });

答案 1 :(得分:1)

您无法在以后的承诺then中访问这些变量,但您可以通过将本地解析值分配给全局变量来解决这些变量

let globalUser, globalPost; // create variables for later

User
    .findById(userId)
    .then(user => {
        globalUser = user; // assign to global
        return Post.findById(postId)
    })
    .then(post => {
        globalPost = post; // assign to global
        return Image.findById(imageId)
    })
    .then(image => {
        // DO SOMETHING WITH VARIABLES 'globalUser', 'globalPost', AND 'image'
    })
    .catch(err => {... });

编辑:或使用async/await时:

async function() {
    const user = await User.findById(userId);
    const post = await Post.findById(postId);
    const image = await Image.findById(imageId);

    // do something with user, post and image
}

看到你的承诺不相互依赖,你也可以在异步函数中使用Promise.all()

async function() {
    const result = await Promise.all([
        User.findById(userId),
        Post.findById(postId),
        Image.findById(imageId)
    ]);

    const [user, post, image] = result;

    // do something with user, post and image
}

编辑2 :错误处理

async function getImage() {
    let user;
    try {
        user = await User.findById(userId);
    } catch (error) { // deal with rejection of `User.findById`
        // do something with error
    }

    // if these fail the entire function will throw
    const post = await Post.findById(postId);
    const image = await Image.findById(imageId);

    return image;
}

getImage()
    .then(image => {... })
    .catch(error => {... }); // deal with rejection of `getImage` as a whole

上面的代码展示了在异步函数中处理错误的方法。第一个是我们如何处理User.findById函数中的错误,只需将其包装在try catch块中即可。

第二种方法是简单地让整个异步函数抛出错误。即如果Post.findByIdImage.findById承诺拒绝,则整个getImage()承诺将拒绝,您可以在.catch()处理程序中处理。