web-dev-qa-db-ja.com

Node.jsでジェネレーターを使用するforEach

Koa.js フレームワークと Mongoose.js モジュールを使用しています。

通常、MongoDBから結果を取得するには、次のようなコードを記述します。

var res = yield db.collection.findOne({id: 'my-id-here'}).exec();

しかし、「items」という名前の配列のすべての要素に対してこの行を実行する必要があります。

items.forEach(function(item) {
  var res = yield db.collection.findOne({id: item.id}).exec();
  console.log(res)  // undefined
});

ただし、yieldが関数内にあるため、このコードは実行されません。これを書けば:

items.forEach(function *(item) {
  var res = yield db.collection.findOne({id: item.id}).exec();
  console.log(res)  // undefined
});

Res変数でも結果が得られません。 ' generator-foreach 'モジュールを使用しようとしましたが、このように機能しませんでした。

これは、Node.jsの言語リテラシーに関する知識の欠如であることを知っています。しかし、これを行う方法を見つけるのを手伝ってくれる?

15
Mazhar Ahmed

みんなありがとう、 ' [〜#〜] co [〜#〜] 'モジュールを使ってこれをやった。ありがとう。

var co = require('co');

items.forEach(co(function* (item) {
  var img = yield db.collection.findOne({id: item.id}).exec();
}));

編集:COの最新バージョンでは、これを機能させるにはco.wrap()が必要です。

6
Mazhar Ahmed

配列をyieldできるので、非同期プロミスを別のマップにマッピングするだけです

var fetchedItems = yield items.map((item) => {
   return db.collection.findOne({id: item.id});
});
21
Umidbek Karimov

受け入れられた答えは間違っています。ライブラリを使用する必要はありません。配列はすでに反復可能です。

これは古い質問ですが、まだ正解がなく、主要な用語「iterators and forEach」のGoogle検索の最初のページに表示されるため、次の質問に回答します。

配列はすでに反復可能なAPIに準拠しているため、配列を反復処理する必要はありません。

ジェネレーターの内部では、「yield *配列」を使用するだけです(*に注意してください)。yield*式は、別のジェネレーターまたは反復可能なオブジェクトに委譲するために使用されます

例:

let arr = [2, 3, 4];

    function* g2() { 
      yield 1;
      yield* arr;
      yield 5;
    }

    var iterator = g2();

    console.log(iterator.next()); // { value: 1, done: false }
    console.log(iterator.next()); // { value: 2, done: false }
    console.log(iterator.next()); // { value: 3, done: false }
    console.log(iterator.next()); // { value: 4, done: false }
    console.log(iterator.next()); // { value: 5, done: false }
    console.log(iterator.next()); // { value: undefined, done: true }

例と詳細情報については、次のWebサイトをご覧ください。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield *

8
Jorge Riv