如何使用async.js异步运行这3个node.js函数?

时间:2017-07-16 02:54:18

标签: javascript node.js express asynchronous async.js

我有3个函数,我想异步运行,当它们全部完成后运行另一个函数:

app.get('/', function (req, res) {

  var homePosts = {
    newsest: [],
    reviewed: [],
    mostPopuler: [],
    viewed: []
  };

  // fetch newest pages and asign the result to 'homePosts.newest '
  function fetchNewestPages() {
    Post.find({ "type": "public", "featuredImage": { "$exists": true } },"_id title briefDes featuredImage", function (err, posts) {
      if (err) {
        req.flash('error', 'An unknown error was occured.');
        res.redirect('back');
      } else {
        homePosts.newsest = posts;
      }
    }).limit(4).sort( { date : -1 } );
  }

  // fetch most reviewed pages and asign the result to 'homePosts.reviewd '
  function fetchMostReviewedPages() {
    Post.find({ "type": "public", "featuredImage": { "$exists": true } },"_id title briefDes featuredImage", function (err, posts) {
      if (err) {
        req.flash('error', 'An unknown error was occured.');
        res.redirect('back');
      } else {
        homePosts.reviewed = posts;
      }
    }).limit(4).sort( { commentsNumber : -1 } );
  }

  // fetch most popular pages and asign the result to 'homePosts.mostPopuler '
  function fetchMostPopularPages() {
    Post.find({ "type": "public", "featuredImage": { "$exists": true } },"_id title briefDes featuredImage", function (err, posts) {
      if (err) {
        req.flash('error', 'An unknown error was occured.');
        res.redirect('back');
      } else {
        homePosts.mostPopuler = posts;
      }
    }).limit(4).sort( { likesNumber : -1 } );
  }

 // now run all 3 functions and when they are done render home page with the homePosts object which contains proper pages
  async.parallel([

    fetchNewestPages,
    fetchMostReviewedPages,
    fetchMostPopularPages

  ], function (err) { // it doesn't run at all
    if (err) throw err;
    console.log(homePosts);
    res.render("home", {homePosts}); // render home page with the proper pages 
  });


});

希望你得到代码的功能,这里是代码所做的描述:

  1. 有homePosts对象,它将在主页上显示正确的页面
  2. 然后我们有一个函数,它将从数据库中获取4个最新页面,然后将它们分配给homePost.newest
  3. 然后是一个函数,它将具有最多评论的4个页面分配给homePost.reviewed
  4. 第三个函数(如上面的2个函数)将最常用的页面分配给homePost.mostPopular
  5. 现在async.js应该完成它的工作,同时运行这3个函数,然后使用homePosts对象呈现主页,这是我遇到问题的部分
  6. 将呈现主页的最后一个功能根本不会运行。我的问题在哪里?有没有办法同时运行这3个函数然后运行最后一个将呈现页面的函数?

    更新:

    我已经设法以这种方式做到了,但他们没有同时运行,他们一个接一个地运行。

    // fetch newest pages and asign the result to 'homePosts.newest '
      function fetchNewestPages(cb) {
        Post.find({ "type": "public", "featuredImage": { "$exists": true } },"_id title briefDes featuredImage", function (err, posts) {
          if (err) {
            req.flash('error', 'An unknown error was occured.');
            res.redirect('back');
          } else {
            homePosts.newsest = posts;
            cb();
          }
        }).limit(4).sort( { date : -1 } );
      }
    
      // fetch most reviewed pages and asign the result to 'homePosts.reviewd '
      function fetchMostReviewedPages(cb) {
        Post.find({ "type": "public", "featuredImage": { "$exists": true } },"_id title briefDes featuredImage", function (err, posts) {
          if (err) {
            req.flash('error', 'An unknown error was occured.');
            res.redirect('back');
          } else {
            homePosts.reviewed = posts;
            cb();
          }
        }).limit(4).sort( { commentsNumber : -1 } );
      }
    
      // fetch most popular pages and asign the result to 'homePosts.mostPopuler '
      function fetchMostPopularPages(cb) {
        Post.find({ "type": "public", "featuredImage": { "$exists": true } },"_id title briefDes featuredImage", function (err, posts) {
          if (err) {
            req.flash('error', 'An unknown error was occured.');
            res.redirect('back');
          } else {
            homePosts.mostPopuler = posts;
            cb();
          }
        }).limit(4).sort( { likesNumber : -1 } );
      }
    
      fetchNewestPages(function () {
        fetchMostReviewedPages(function () {
          fetchMostPopularPages(function () {
              res.render("home", {homePosts});
          });
        });
      });
    

3 个答案:

答案 0 :(得分:2)

您的问题是您的任何功能都没有回调参数。请记住,当一个函数的处理完成时,您必须调用回调方法。

我在练习中所做的是使用async.constant作为async.waterfallasync.parallel的第一种方法,并传递将在异步方法中使用的数据。在您的情况下,它可以是所有三种方法的搜索条件。 如果在异步方法中没有使用数据,那么我只传递一个空的JS对象。

使用async.constant可以帮助我做两件事。

  1. 传递要在异步方法中使用的数据。
  2. 从该传递的对象中获取异步方法的结果。
  3. 在您的情况下,async.constant方法将包含homePosts个对象。

        app.get('/', function (req, res) {
    
          // fetch newest pages and asign the result to 'homePosts.newest '
          function fetchNewestPages(data, callback) {
              Post
              .find({ "type": "public", "featuredImage": { "$exists": true } },"_id title briefDes featuredImage")
              .limit(4)
              .sort( { date : -1 } )
              .exec(function (err, posts) {
                 if (err) {
                   //If we pass first parameter as non-null, the control is passed to the last optional callback skipping all other functions in case of async.waterfall and not waiting for other functions to complete in case of async.parallel
                   return callback('An unknown error was occured.');  
                 } else {
                   data['newsest'] = posts; //since homePosts is data object inside this function
                   If this function is completed successfully then we pass first parameter as null (no error) and second parameter as our object. As the strategy is parallel, all three functions will be editing the same object 'homePosts'
                   return callback(null, data);
                 }
              });
          }
    
          // fetch most reviewed pages and asign the result to 'homePosts.reviewd '
          function fetchMostReviewedPages(data, callback) {
              Post
              .find({ "type": "public", "featuredImage": { "$exists": true } },"_id title briefDes featuredImage")
              .limit(4)
              .sort( { commentsNumber : -1 } )
              .exec(function (err, posts) {
                 if (err) {
                   //read comment in first function
                   return callback('An unknown error was occured.');
                 } else {
                   data['reviewed'] = posts; //since homePosts is data object inside this function
                   //read comment in first function
                   return callback(null, data);
                 }
              });
          }
    
          // fetch most popular pages and asign the result to 'homePosts.mostPopuler '
          function fetchMostPopularPages(data, callback) {
              Post
              .find({ "type": "public", "featuredImage": { "$exists": true } },"_id title briefDes featuredImage")
              .limit(4)
              .sort( { likesNumber : -1 } )
              .exec(function (err, posts) {
                 if (err) {
                   //read comment in first function
                   return callback('An unknown error was occured.');
                 } else {
                   data['reviewed'] = posts; //since homePosts is data object inside this function
                   //read comment in first function
                   return callback(null, data);
                 }
              });
          }
    
          var homePosts = {
            newsest: [],
            reviewed: [],
            mostPopuler: [],
            viewed: []
          };
    
          // now run all 3 functions and when they are done render home page with the homePosts object which contains proper pages
    
          async.parallel([
            async.constant(homePosts),
            fetchNewestPages,
            fetchMostReviewedPages,
            fetchMostPopularPages
          ], function (err, data) {
                //once all functions complete their execution and their callback method is called, with or without error, this method will be called. 
                if (err) {
                  req.flash('error', err);
                  res.redirect('back');
                } else {
                  console.log(data);
                  res.render("home", {data}); // render home page with the proper pages 
                }
          });
    });
    

    希望能够解决您的问题并清除您的概念。

答案 1 :(得分:1)

异步库适用于使用回调的函数。你们没有人这样做。

要么以回调形式重写它们,要么使用像Promise.all这样的东西:

long long t1_rdtsc, t2_rdtsc, ttotal_rdtsc[do_while], ttbest_rdtsc = 99999999999999999, elapsed,  elapsed_rdtsc=do_while, overal_time = OVERAL_TIME, ttime=0;
int ii=0;
    #define begin_rdtsc\
                    do{\
                        asm("#mmmmmmmmmmm");\
                        t1_rdtsc=_rdtsc();

    #define end_rdtsc\
                        t2_rdtsc=_rdtsc();\
                        asm("#mmmmmmmmmmm");\
                        ttotal_rdtsc[ii]=t2_rdtsc-t1_rdtsc;\
                    }while (ii++<do_while);\    
                    for(ii=0; ii<do_while; ii++){\
                        if (ttotal_rdtsc[ii]<ttbest_rdtsc){\
                            ttbest_rdtsc = ttotal_rdtsc[ii];}}\             
                    printf("\nthe best is %lld in %lld iteration\n", ttbest_rdtsc, elapsed_rdtsc);

答案 2 :(得分:0)

希望这有助于你

console.log('start');

// fetch newest pages and asign the result to 'homePosts.newest '
function fetchNewestPages() {
console.log('1')
}

// fetch most reviewed pages and asign the result to 'homePosts.reviewd '
function fetchMostReviewedPages() {
console.log('2')
}

// fetch most popular pages and asign the result to 'homePosts.mostPopuler '
function fetchMostPopularPages() {
console.log('3')
}


fetchNewestPages();
console.log('1 DONE');
fetchMostReviewedPages();
console.log('2 DONE');
fetchMostPopularPages();
console.log('3 DONE');

我的工作也很多。作为示例如果我有很多回调并且某些东西突然不同步那么这个技巧可能很好

var obj = {}

// to somelong stuff here and the result is var result
var result = 'this was generated in the fictive long process above'
objectme.obj = result // those object string can be used anywhere in the script realy nice.

clearInterval(testinterval); // <-- do also here a clearinterval
var testinterval = setInterval(function(){

if (objectme.obj) {
clearInterval(testinterval);
//.. the interval only stop here at the if. you can do anything here. also you can make a timeout. This will force the script to run as you wish it
}

},10000);

非常重要。如果您计划将长代码插入clearinterval区域,则需要增加间隔时间。如果插入的代码花费的时间超过了间隔,那么您的代码将被执行2次。

但是你应该在第一个例子中做。因为使用间隔可能非常棘手。