Node.js同步返回多个asynchronous收益的结果

我正在使用rethinkDB与node.js. 以下请求正常工作:

function myFn () { return co(function *() { let query; query = yield r.db("my-db") .table("app") .filter(r.row("id").eq(id)) .run(conn); return query.toArray(); }); } 

我想asynchronous返回多个yield的结果,但是下面的失败:

 function myFn () { return co(function *() { let query, query2; query = r.db("my-db") .table("app") .filter(r.row("id").eq(id)) .run(conn); query2 = r.db("my-db") .table("app") .filter(...) .run(conn); return yield {q1 : query, q2 : query2}; }); } 

然后我必须在每个元素上调用toArray() ,所以在调用函数中我会这样做:

  // using ramda.js var res = R.map((el) => { return el.toArray(); }, yield myFn); 

但是我得到:

 { "q1": { "isFulfilled": false, "isRejected": false }, "q2": { "isFulfilled": false, "isRejected": false } } 

也有一些奇怪的东西:

  // this works perfectly return q.toArray(); // this returns the following : return {q: q.toArray()}; "q": { "isFulfilled": true, "isRejected": false, "fulfillmentValue": [ ... ] } 

我怀疑我缺less一些关于yield的方法,那么我怎样才能返回多个yield结果的实现结果呢?

yield不适用于包含承诺的对象 – 它只能与承诺本身一起工作。 而不是return yield {q1: query, q2: query2}; 你必须这样做

 return {q1: yield query, q2: yield query2}; 

然而,这是有点问题,因为query2错误将不会被抛出,直到query完成。 所以,如果你不只是想顺序执行它们 ,你将不得不使用Promise.all来“等待”一系列的承诺:

 var [q1, q2] = yield Promise.all([query, query2]); return {q1, q2}; 

(根据你使用的promise lib,可能还有一个辅助函数将对象视为集合,而不仅仅是数组)

所以我问了reThinkDB google groups的同样的问题:

引用瑞安·保罗的话:

你原来的尝试实际上非常接近,只需要添加两件事:

  • 您需要单独产生查询
  • 如果您不想获取游标,则需要在查询中转换为数组

下面是一个使用协程和yield的例子:

 function myFn() { return co(function*() { var conn = yield r.connect(); var query1 = yield r.db("test").table("fellowship") .filter({species: "hobbit"}) .coerceTo("array").run(conn); var query2 = yield r.db("test").table("fellowship") .filter({species: "human"}) .coerceTo("array").run(conn); conn.close(); return {q1: query1, q2: query2}; }); } 

如果没有协程和产量,也很简单,只要你使用蓝鸟这样的承诺库。 以下是我将如何做到这一点:

 function myFn1() { return r.connect().then(conn => { return bluebird.all([ r.db("test").table("fellowship") .filter({species: "hobbit"}) .coerceTo("array").run(conn), r.db("test").table("fellowship") .filter({species: "human"}) .coerceTo("array").run(conn) ]).then(items => ({q1: items[0], q2: items[1]})); }); }