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