How to use promise to avoid callback hell?

This question already has an answer here:

  • Aren't promises just callbacks? 7 answers

  • Try whit this:

    function getPost(id) {
      return Post
        .findOne({id: id})
        .then( post => {
          return post;
        });
    }
    

    using Q module

    function getCommentsAndLinks(post) {
      return Q.all([
        Comment.find({id: post.id}),
        Links.find({id: post.id})
      ])
      .done( results => {
        let comments = results[0];
        let links = results[1];
        return [post, comments, links];
      })
      .catch( err => {
      // handle err
      })
    

    on controller

    getPost(postId)
    .then(getCommentsAndLinks)
    .then( results => {
      let post = results[0];
      let comments = results[1];
      let links = results[2];
      // more code here
    })
    .catch( err => {
    // handle err
    }) 
    

    but i suggest you not save string of IDS, save the instance of object, so you can use populate to get all data of comments and links, something like this:

    Post
    .findOne({id: id})
    .populate('comments')
    .populate('links')
    .then( post => {
        // here have the post with data of comments and links
    });
    

    You are nesting the callbacks. You don't need to do this. If you return a promise from .then then any .then you chain to it will be resolved when that promise gets resolved:

    promise.then(post => Comments.find({id: post.id})
      .then(comments => Links.find({id: post.id})
      .then(links => {});
    

    The comments query does not depend on links so you can actually do both queries at once:

    promise.then(post => {
      return Promise.all([
         post,
         Comments.find({id: post.id}),
         Links.find({id: post.id}),
      ]);
    }).then(data => res.json({
      post: data[0],
      comments: data[1],
      links: data[2],
    });
    

    If you use a library like bluebird you can also use something like the spread operator to make the names more transparent.


    I would also look into using co for generator-based control flow as I think this is even clearer:

    co(function* () {
      const post = yield Posts.findOne({id});
      const [comments, links] = yield [
        Comments.find({id: post.id}),
        Links.find({id: post.id}),
      ];
    
      res.json({post, comments, links});
    });
    

    The advantage of using promises is you can chain them, so your code can be reduced to:

    let post, comments;
    Posts.findOne({id: id}).exec().then(_post => {
        post = _post;
        return Comments.find({id: post.id}).exec();
      }).then(_comments => {
        comments = _comments;
        return Links.find({id: post.id}).exec();
      }).then(links => res.json({post, comment, links}))
      .catch(error => res.error(error.message));
    

    you would notice that I needed only a single catch block.

    链接地址: http://www.djcxy.com/p/55440.html

    上一篇: 回调还是承诺?

    下一篇: 如何使用promise来避免回调地狱?