Search code examples
javascriptnode.jspromisecouchdbcouchdb-nano

Using nano-promises to force synchronous CouchDB queries and updates


I am using nano-promise to attempt to force the following code in node.js to run in series. However, the below promises appear to still complete before the first CouchDB insert is complete. This causes an issue because later promises will have code that will query CouchDB and expect that the code in the previous step(s) is complete. I believe the issue is because return is being executed immediately after db.get, and before db.get completes. Does anyone have any suggestions on how to solve this problem?

var nano = require('nano')('http://localhost:5984');
var Promise = require('nano-promise');
var db = nano.db.use('myDB');

var promise = new Promise(function (resolve, reject) {
    resolve(request);
}).then(function (args) {
    console.log('step 1');
    console.log(args.body);
    db.get(args.body.id, function(err, body) {
        var doc_update = body;
        if (!err) {
            doc_update.beginDate = args.body.startDate;
            doc_update.updated = new Date();
            db.insert(doc_update, args.body.id, function(err, body){
                if(!err){
                    console.log('Database UPDATED (Step 1)');
                }
            });
        } else {
            doc_update.updated = new Date();
            db.insert(doc_update, args.body.id, function(err, body){
                if (err) throw err; 
            });
        }
    });
    return new Promise.Arguments(args);
}).then(function (args) {
    console.log(args.body);
    return new Promise.Arguments(args);
});
promise.then(function (args) {
    console.log(args.body);
    return new Promise.Arguments(args);
});
promise.then(function (args) {
    console.log(args.body);
});

The output of this code is:

step 1
{id: '123',
startDate: '2017-12'}
step 2
{id: '123',
startDate: '2017-12'}
step 3
{id: '123',
startDate: '2017-12'}
step 4
{id: '123',
startDate: '2017-12'}
Database UPDATED (Step 1)

The output should be:

step 1
{id: '123',
startDate: '2017-12'}
Database UPDATED (Step 1)
step 2
{id: '123',
startDate: '2017-12'}
step 3
{id: '123',
startDate: '2017-12'}
step 4
{id: '123',
startDate: '2017-12'}

Solution

  • According to the documentation you are using nano-promise wrong. You use it to create a db object that returns promises on insert and get.

    You seem to have tripple nested promises, the code should look something like this:

    var db = prom(nano('http://localhost:5984')).db.use('myDB');
    
    var promise = Promise.resolve(request)
    .then(function (args) {
      console.log('step 1');
      console.log(args.body);
      return db.get(args.body.id)
      .catch(
        err => {
          var doc_update = body;
          doc_update.updated = new Date();
          return db.insert(doc_update, args.body.id)
          .then(x=>args);
        }
      )
      .then(
        body => {
          var doc_update = body;
          doc_update.beginDate = args.body.startDate;
          doc_update.updated = new Date();
          return db.insert(doc_update, args.body.id)
          .then(
            ok => {
              console.log('Database UPDATED (Step 1)');
              return args;
            },
            err => {
              console.log("Failed UPDATE (Step 1)");
            }
          );
        }
      )
    }).then(function (args) {
      console.log(args.body);
      return args;
    });