MHogge
MHogge

Reputation: 5196

Wait for queries results

I'm using the Couchbase nodeJS SDK. To make a query I must call bucket.query("SELECT ...", function(err, rows){console.log("query's result received")})

I would like to run queries sequentially like :

  1. Run query A
  2. Work on result A
  3. Run query B
  4. Work on result B
  5. ...
  6. Continue after all results has been reveived and handle

Or even better it could be

  1. Run all queries
  2. Work on results one by one as they are being reveived
  3. Continue after all results has been reveived and handle

The point is I dont know how to wait for all the queries to be finished before continuing. I tought of promises but I'm new to nodeJS and I'm not sure I used them correctly, maybe someone could point me to the right direction ?

I saw that the async/await feature is available in node but I didn't manage to make it working either.

Any help would be apprecietate !


EDIT

I tried to use couchbase-promises but I still don't get the behavior I expect. Here is what I've done:

console.log("start");
bucket.queryAsync(N1qlQuery.fromString('SELECT * FROM DATA_BUCKET WHERE type="BOOK"'))
  .then(function(rows){console.log("success")})
  .catch(function(err){console.log(err)})
console.log("end");

But the output shows

start
end
success

What I would like is

start
success
end

I also tried const rows = await bucket.queryAsync("SELECT...) but I got an Unexpected identifiererror. I found on this SO post that it means the method queryAsync does not have the async keyword.

Any idea on how I could achieve my expected behavior? Thank's !

Upvotes: 1

Views: 7241

Answers (3)

Asad
Asad

Reputation: 3160

You can use Async water fall library its best library for serialize the function one by one here is link water fall library it will start executing from first function and will go till last function

Upvotes: 0

Ezra Chu
Ezra Chu

Reputation: 832

Promise.all() allows you to run a list of promises and wait for all fulfillments (or the first rejection). You'll have to use something like couchbase-promises or promisify yourself using Bluebird or Q, because the Couchbase SDK does not return promises.

Once you have a query returning as a promise, you can just stack up your queries in an array, and pass it to Promise.all(). This will return a new promise that resolves with an array of results.

list = [
  bucket.query("SELECT ..."),
  bucket.query("SELECT ..."),
  bucket.query("SELECT ...")
]
Promise.all(list).then(function(results){
  // results is an array
}).catch(function(err){
  // err is the first rejection encountered
})

If you wanted to use async/await here, you could do something like this:

[r1, r2, r3] = await Promise.all(list)

Upvotes: 2

notgiorgi
notgiorgi

Reputation: 1771

The naivest way to do that would be to use callbacks:

bucket.query('SELECT ...', function(err, rows) {
  bucket.query('SELECT ...', function(error, moreRows) {
    bucket.query('SELECT ...', function(...) {
      // sent data to client or something
    })
  })
})

but, this leads to the callback hell, which needs to be avoided, so you should prefer using Promises

there already exists a port for couchbase from callbacks to promises: https://www.npmjs.com/package/couchbase-promises

this converts callbacks to this:

bucket.query('SELECT ....')
    .then(successCallback)
    .catch(errorCallback)

after that you might even consider async/await which would make your code even more readable:

try {
    const rows = await bucket.query(...)
    // do other things
catch (e) {
    // handle errors
}

Upvotes: 4

Related Questions