2012-05-04 7 views
5

node.jsの非同期性に関する助けが必要です。私はデータベースからデータを収集するforループを持っています。 "result"は配列で、main関数に返す必要があります。node.jsのfor-loop終了後のコールバック

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:のuserId \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、関数(コンタクト、コールバック){ \t \t \t \t \t \tにconsole.log(コンタクト) \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場合: \t \t \tをcontact.contactId \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

答えて

10

あなたはforEach()方法

forEach(arr, iterator, callback) 
で見ることができ、それは、より一貫性のあるコードを保持するのに役立ちます https://github.com/caolan/async

非同期..あなたの場合

のようなヘルパーライブラリを使用して検討する必要があります

イテレータは、リストからアイテムを呼び出してコールバックを終了します。

アウト例Async.jsのv1.5.2で

https://github.com/caolan/async/blob/master/mocha_test/each.js

+0

ありがとう!私は今それを使用しており、それは動作します! – johnny

0

ためのユニットテスト、それはeachあります。反復処理するための配列 - ARR

each(arr, iterator, [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')) 

プロセスなしに、すべての非同期要求"同期" の実行が

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

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

(2よりも速く1を終了してもよい)、私はそのようにそれをやった

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

マイケル。

関連する問題