2012-05-04 36 views
5

我需要一些關於node.js異步特性的幫助。我有一個for循環,它從數據庫收集數據。 「結果」是一個數組,然後應該返回到主函數。node.js中for循環完成後的回調

user_collection.findOne({ 
      _id : uid 
     }, function(error, user) { 
      if(error) 
       callback(error) 
      else { 
       for(var j = 0; j < user.contacts.length; j++) { 
        if(user.contacts[j].accepted == 'true') { 
         user_collection.findOne({ 
          _id : user.contacts[j].contactId 
         }, function(error, user) { 
          result.push(user); 
         }) 
        } 
       } 
       callback(null, result); // This callback executes before the for-loop ends, ofc 
      } 
     }); 

如何確保循環完成後執行回調?

+0

使用async:'user_collection的工作版本。findOne({ \t \t \t \t _id:用戶id \t \t \t},功能(錯誤,用戶){ \t \t \t \t如果(誤差) \t \t \t \t \t回調(誤差) \t \t \t \t否則{ \t \t \t \t \t async.forEach(user.contac ts,function(contact,callback){ \t \t \t \t \t \t console.log(contact); \t \t \t \t \t \t如果(contact.accepted == '真'){ \t \t \t \t \t \t \t user_collection.findOne({ \t \t \t \t \t \t \t \t _id:contact.contactId \t \t \t \t \t \t \t},fu nction(誤差,接觸){ \t \t \t \t \t \t \t \t result.push(接觸); \t \t \t \t \t \t \t \t callback(); \t \t \t \t \t \t \t}) \t \t \t \t \t \t} \t \t \t \t \t},函數(誤差){回調(錯誤,結果)}) \t \t \t \t} \t \t \t} );' – johnny

回答

0

隨着Async.js的V1.5.2單元測試,這是each

each(arr, iterator, [callback]) 

ARR - 一個數組遍歷。
迭代器(item,callback) - 應用於arr中每個項目的函數。
回調(錯誤) - 可選。 所有迭代器函數已完成或發生錯誤時調用的回調

1

使用ES6諾言 (一個承諾庫可用於舊的瀏覽器):

過程保證同步執行(例如,1,然後2然後3)

function asyncFunction (item, cb) { 
    setTimeout(() => { 
    console.log('done with', item); 
    cb(); 
    }, 100); 
} 

let requests = [1, 2, 3].reduce((promiseChain, item) => { 
    return promiseChain.then(new Promise((resolve) => { 
     asyncFunction(item, resolve); 
    })); 
}, Promise.resolve()); 

requests.then(() => console.log('done')) 

處理所有異步請求,而不所有請求「同步」 執行(2可以更快地完成比1)

let requests = [1,2,3].map((item) => { 
    return new Promise((resolve) => { 
     asyncFunction(item, resolve); 
    }); 
}) 

Promise.all(requests).then(() => console.log('done')); 

我做到了對這樣

Promise.all(body.schedules.map(function(scheduleId) { 
     return new Promise(function(resolve, reject) { 
      return scheduleSchema.findOneAndRemove({ 
        _id: scheduleId 
       }) 
       .then(function() { 
        logSchema.insert({ 
         userId: req.user.id, 
         actId: constants.LOG_SCHEDULE_DELETE.id, 
         extData: scheduleId 
        }); 
        resolve(); 
       }) 
       .catch(function(err) { 
        reject(err); 
       }); 
     }); 
    })).then(function() { 
     return res.json({ 
      code: constants.SUCCESS_CODE 
     }); 
    }).catch(function(err) { 
     return res.json(constants.DATABASE_ERROR); 
    }); 

最後一個例子

function callback (result) { console.log('all done'); } 

[1, 2, 3].forEach((item, index, array) => { 
    asyncFunction(item,() => { 
    if (index === array.length - 1) { 
     callback(); 
    } 
    }); 
}); 

這並不能保證所有的項目都處理後回調將執行。它只保證在處理最後一個項目後執行回調。

More information

邁克爾。