NodeJS promises with rethinkDB

477 Views Asked by At

I have a question regarding promises in nodeJS when using Rethindb. This code will give me the results from db first time anything changes, not more.

Lets say I start the script and add a row to the db, the new data will be printed in cmd. But if I add another one, nothing are shown. Something wrong with the way I use the promise? (and no, I dont want to use callback)

Thx!

PushData(r, table)
.then(res=>{
  console.log(res);
}


function PushData(r, table){
  return new Promise(function(resolve, reject){
    r.table(table)
    .changes()
    .run()
    .then(function(cursor){

      cursor.on("error", function(err) {
        reject(err)
      })
      cursor.on("data", function(data) {
        resolve(data);
      })
    });
  });
}
3

There are 3 best solutions below

0
On

A promise is only resolving to one value, and calling resolve() multiple times on a promise only return that value each time. That's not what you want.

What you want to do instead is to repeatedly call cursor.next() to get more values, one promise after another.

However, you may be also interested by another similar feature of ES6: the Asynchronous Iterator.

Here is my code for converting the cursor from rethinkdb into an async iterator:

import { $$asyncIterator } from 'iterall'

// Transform the cursor's stream into an Async Iterator.
function feedToAsyncIterator (p) {
  return {
    next () {
      return p.then(async cursor => {
        try {
          // See https://www.rethinkdb.com/api/javascript/next/
          const row = await cursor.next()
          return {value: row, done: false}
        }
        catch (e) {
          return {done: true}
        }
      })
    },
    [$$asyncIterator]() {
      return this
    }
  }
}

const myChangeFeed = r.table('myTable').changes().run(db)

// You can enumerate the changes from inside an async function this way:
for await (const change of feedToAsyncIterator(myChangeFeed)) {
  console.log('change:', change)
}
0
On

Yes, you are conflating "promises" with "callbacks". A fundamental principle of a Promise is that it can only be fulfilled ONCE. After it has been resolved or rejected (the two ways it can be fulfilled), it cannot be operated on again.

Callbacks are not evil. This is the time to use them.

0
On

My understanding is you have an asynchronous function that you want to call twice. for example, you want to insert two rows to DB you will call the function twice.

const PushData = async (r, table) => {
    try {
        const res = await new Promise(function (resolve, reject) {
            r.table(table)
                .changes()
                .run()
                .then(function (cursor) {

                    cursor.on("error", function (err) {
                        reject(err)
                    })
                    cursor.on("data", function (data) {
                        resolve(data);
                    })
                });
        });
        return res
    } catch (error) {
        throw error
    }
}

var res1 = await PushData(r,table)
console.log("result 1 is ==> "+res1)
var res2 = await PushData(r,table)
console.log("result 2 is ==> "+res2)