Node.js同步返回多个异步yield的结果

时间:2015-11-20 09:55:33

标签: node.js promise ecmascript-6 yield rethinkdb

我正在使用带有node.js的rethinkDB。以下请求可以正常工作:

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

我想异步返回多个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": [  ...  ]
  }

我怀疑我遗漏了yield的工作方式,所以如何才能返回多个yield结果的实现结果?

2 个答案:

答案 0 :(得分:1)

yield不能处理包含promises的对象 - 它只适用于promises本身。而不是return yield {q1: query, q2: query2};你必须做

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

然而,这有点问题,因为在query2完成之前不会抛出query中的错误。因此,如果您不是just want to sequentially execute them,则必须使用Promise.all来等待承诺的集合"并行":

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

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

答案 1 :(得分:1)

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

引用Ryan Paul的话:

  

你原来的尝试实际上非常接近,只有两次   你需要添加的东西:

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

这是一个关于协程和产量的工作示例:

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