2015-11-20 4 views
1

Я использую rethinkDB с node.js. Следующий запрос работает отлично: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(); 
    }); 
} 

Я хотел бы вернуть результат многократного 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 результатов?

+1

Как это не в состоянии точно? Вы получили сообщение об ошибке? Получаете ли вы другой результат, чем ожидалось? – nils

+0

'yield {q1: r.db (" "), q2: r.db (" ")};'. –

+0

@nils Я обновил свой вопрос, спасибо. – nha

ответ

1

Так что я задал тот же вопрос о reThinkDB google groups:

цитирую Ryan Пол:

Ваш Ori ginal попытка была на самом деле очень близко, там были только две вещи, которые вам нужно добавить:

  • Вы должны дать запросы индивидуально
  • И вам необходимо преобразовать в массив в запросе, если вы этого не сделаете хочу получить курсоры

Вот рабочий пример с сопрограммой и выходом:

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

Это также довольно просто сделать остроумие hout coroutines и yield, а также как , поскольку вы используете библиотеку обещаний, такую ​​как bluebird. Вот как я бы его:

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

ОК, поэтому '.coerceTo (" array ")' был недостающей частью моего ответа. Спасибо за обновление! – Bergi

1

yield не работает с объектами, которые содержат обещания - он работает только с обещаниями. Вместо 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}; 

(В зависимости от обещания Lib вы используете, может быть также вспомогательной функцией для лечения объектов как коллекции, а не только массивы)

+0

Первый подход по-прежнему возвращает '' '{ "isFulfilled" ложь, "isRejected": ложные } '' ', в то время как второй подход (Promise.all) по-прежнему возвращает ReThink курсоров (' '' [Курсор { _type: 3, _eachCb: [Функция] , _conn: TCPConnection { хозяин: 'локальный', порт: 28015, дБ не определено, authKey: '', тайм-аут: 20, ssl: false, excellentCallbacks: [Object], .... '' ' – nha

+0

Хм, это не похоже на' run() 'возвращает обещание. Должен ли вы, скорее, «уронить» результат '.toArray()'? Я не совсем знаком с переосмыслением, но это не похоже на то, что курсоры являются допустимыми или доступными. – Bergi

+0

'run()' возвращает курсор, я понимаю, что его можно использовать с доходностью, как в моем первом примере (также есть https://rethinkdb.com/blog/rethinkdbdash-iojs/). – nha

Смежные вопросы