6

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

ループが終了した後にコールバックが実行されるようにするにはどうすればよいですか?

4

3 に答える 3

11

asynchttps ://github.com/caolan/asyncのようなヘルパーライブラリの使用を検討することをお勧めします

コードの一貫性を保つのに役立ちます。

あなたの場合、forEach()メソッドを見ることができます

forEach(arr, iterator, callback)

イテレータは、リストの項目と、それが終了したときのコールバックを使用して呼び出されます。

例については、単体テストを確認してください

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

于 2012-05-04T12:06:42.327 に答える
2

ES6 Promisesの使用(Promiseライブラリは古いブラウザーで使用できます):

同期実行を保証するすべてのリクエストを処理します(例: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();
    }
  });
});

これは、すべてのアイテムが処理された後にコールバックが実行されることを保証するものではありません。最後のアイテムが処理された後にコールバックが実行されることを保証するだけです。

詳しくは

マイケル。

于 2016-08-02T15:34:49.227 に答える
0

Async.jsのv1.5.2では、それぞれです。

each(arr, iterator, [callback])

arr-反復する配列。
iterator(item、callback) -arrの各アイテムに適用する関数。
callback(err) -オプション。すべてのイテレータ関数が終了したとき、またはエラーが発生したときに呼び出されるコールバック。

于 2016-02-01T07:36:09.680 に答える