1

I'm trying to untangle a huge mess of callback-based code for node and it seems like promises hold the key to that as I have lots of async database operations. Specifically I am using Bluebird.

I am stuck on how to handle a function which needs to either retrieve data from the DB and set certain values on this. The end goal I am trying to accomplish is something like:

myobj.init().then(function() {
  return myobj.doStuff1();
}).then(function() {
  return myobj.doStuff2();
}).catch(function(err) {
  console.log("Bad things happened!", err);
});

Particularly init, doStuff1 and doStuff2 need to run only when the previous one has completed, but they all do (multiple) asynchronous operations.

This is what I have for init so far, but I don't know how to finish it:

Thing.prototype.init = function(force) {
  if (!this.isInitialized || force) {
    return datbase.query("...").then(function(results){
       // ... use results to configure this
    }).catch(function(err){
       console.log("Err 01");
       throw err;
    });
  } else {
    // ???
    // No data needs to be retrieved from the DB and no data needs to be returned per-se because it's all stored in properties of this.
    // But how do I return something that is compatible with the other return path?
  }
}

Edit: While the duplicated question linked explained a similar pattern, it didn't quite answer my problem as it didn't make it clear I could resolve a promise with nothing.

Praal
  • 15
  • 1
  • 7
  • Did my answer help you at all? If so please click the checkmark so future viewers know it helped. – Datsik Feb 27 '16 at 03:49

1 Answers1

1

If I understand your question correctly, you can just do something like:

Thing.prototype.init = function(force) {
    if (!this.isInitialized || force) {
        return datbase.query("...").then(function(results){
           // ... use results to configure this
        }).catch(function(err){
           console.log("Err 01");
           reject(err);
           throw err;
        });
    } else {
        // ???
        // No data needs to be retrieved from the DB and no data needs to be returned per-se because it's all stored in properties of this.
        // But how do I return something that is compatible with the other return path?
       return Promise.resolve();
    }
  }
}

Just return Promise.resolve(); from your else function.

Datsik
  • 14,453
  • 14
  • 80
  • 121
  • Avoid the [`Promise` constructor antipattern](http://stackoverflow.com/q/23803743/1048572) – Bergi Feb 27 '16 at 05:19
  • @Bergi I think I fixed it? Never heard of this before, but it's good stuff. – Datsik Feb 27 '16 at 06:23
  • You don't need both `reject` and `throw`. Either will do. – jib Feb 27 '16 at 22:18
  • @jib From what I understand he wants to continue his `.then` chain if his `if` statement is `false`, so if you `reject` or `throw` you're going to go straight to the catch and not continue the `then` chain – Datsik Feb 27 '16 at 22:20
  • I don't know what he wants, I just know that `reject` is undefined in your answer, and that `reject(x)` and `throw(x)` in general do the exact same thing inside a chain (ok the latter doesn't execute any subsequent statements inside the function, but that's it). – jib Feb 27 '16 at 22:25
  • Thank you for your answer @Datsik, it really cleared up the core of my dilemma which was not knowing I can `Promise.resolve()` not just `Promise.resolve(someValueOrFunction)`. My intent was: If the content is loaded, resolve the promise so outside code can chain operations based on that. If the content is not loaded, then start loading it and return the promise from the promise-based DB library. If the load succeeds, process the data then resolve the promise. If the load fails, log the error and pass on the rejected promise from the DB to the calling code. – Praal Feb 29 '16 at 04:37