2017-07-16 90 views
0

我有3個功能,我想異步運行,當他們完成所有的工作運行另一個功能:如何使用async.js異步運行這3個node.js函數?

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頁有mosts意見homePost.reviewed
  4. 第三功能,如2以上的功能分配最熱門的網頁,以homePost.mostPopular
  5. 現在async.js應該做的工作的功能,運行這些3個功能同時再渲染主頁與homePosts對象,這是一部分,我有問題

最後一個函數將呈現主頁沒有運行在所有。我的問題在哪裏?有什麼辦法可以同時運行這3個函數,然後運行最後一個會渲染頁面的函數嗎?

UPDATE:

我已經成功地做到這一點通過這種方式,但他們不是同時運行時,它們正在運行一個接一個。

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

回答

1

異步庫適用於使用回調函數。你們都沒有。

要麼重寫它們回調的形式,或使用類似Promise.all:

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

我這樣做:Promise.all( [fetchNewestPages, fetchMostReviewedPages, fetchMostPopularPages]) 。然後(RES =>的console.log(homePosts)) .catch(ERR =>的console.log(ERR))但homePosts是空的,這意味着函數沒有運行。 – Joseph

+0

是否可以使用回調運行這些函數,以便我可以使用異步? – Joseph

+0

homePosts爲空,因爲數據在該示例中以「res」返回。 Promise.all返回一個promise數組,所以試試:'Promise.all([fetchNewestPages,fetchMostReviewedPages,fetchMostPopularPages]).then((res)=> {console.log(res); console.log(res [0] ); console.log(res [1]); console.log(res [2]);}).catch((err)=> {console.log(err);})' – agm1984

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

真的很重要。如果您打算將長碼插入清除間隔區域,則需要增加間隔時間。如果您插入的代碼比間隔時間長,那麼您的代碼將被執行2次。

但是你應該像第一個例子那樣做。因爲使用間隔可能非常棘手。

+0

我已經完成了像你的,但我必須在結束setTimeout(function(){res.render(「home」,{homePosts});},1000);因爲我應該等到所有3個功能完成運行。但我不想這樣做。 – Joseph

+0

對不起,我不明白。如果你使用「;」那麼一切都會在彼此之後超越。 function atend(){ res.render(「home」,{homePosts}); } atend(); – t33n

+0

不,它們是異步運行的,當第一個函數運行時,node.js將進入下一行。我談論你的第一種方法不使用間隔。 – Joseph

2

你的問題是你沒有任何函數的回調參數。請記住,當一個函數的處理完成時,你必須調用回調方法。

我在練習中的做法是使用async.constant作爲async.waterfallasync.parallel的第一個方法,並傳遞要在異步方法中使用的數據。在你的情況下,它可以作爲所有三種方法的搜索標準。 如果沒有數據要用於異步方法,那麼我只傳遞一個空的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 
      } 
     }); 
}); 

希望能夠解決您的問題並更清楚您的概念。

+0

這應該被接受爲正確的答案。 –