簡體   English   中英

如何使用async.js異步運行這3個node.js函數?

[英]How can I run this 3 node.js functions asynchronously using 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應該執行其工作,同時運行這三個功能,然后使用homePosts對象呈現主頁, 這是我遇到的問題

呈現主頁的最后一個功能根本沒有運行。 我的問題在哪里? 有什么辦法可以同時運行這三個功能,然后運行將渲染頁面的最后一個功能?

更新:

我已經設法做到了,但是它們並沒有同時運行,而是一個接一個地運行。

// 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});
      });
    });
  });

您的問題是您的任何函數中都沒有回調參數。 記住,一個函數的處理完成后,必須調用回調方法。

我在實踐中async.constant是將async.constant用作async.waterfallasync.parallel的第一種方法,並傳遞要在async方法中使用的數據。 在您的情況下,它可以作為這三種方法的搜索標准。 如果異步方法中不使用任何數據,那么我只需傳遞一個空的JS對象。

使用async.constant可以在兩方面幫助我。

  1. 傳遞要在異步方法中使用的數據。
  2. 從該傳遞的對象中的異步方法獲取結果。

在您的情況下, 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 
            }
      });
});

希望能解決您的問題並進一步闡明您的概念。

異步庫可與使用回調的函數一起使用。 你們都不做。

要么以回調形式重寫它們,要么使用Promise.all之類的東西:

Promise.all(
    [fetchNewestPages,
    fetchMostReviewedPages, 
    fetchMostPopularPages])
        .then(res => console.log(res[0], res[1], res[2]))
         .catch(err => console.log(err))

希望這對您有所幫助

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次。

但是,您應該在第一個示例中喜歡。 因為使用間隔可能非常棘手。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM