0

[EDIT : since this is a basic question which expects a basic answer,

I added my own answer below, in the question itself

. For more complete information, follow the "duplicate" link, or this helpful example provided in the comments]


QUESTION :


I have recently learned how to use promises, and I am very happy because now I can avoid callbacks in my asynchronous code :

asyncFunction1()
.then(asyncFunction2)
.then(asyncFunction3)
.catch( (err) => {/*handle*/} );

But I am limited to USING those asynchronous functions. Now I want to CREATE my own asynchronous functions when needed :

myCustomAsyncFunction() 
.then(asyncFunction1)  // asyncFunction1 expects a String parameter : "customResult"
.catch( (err) => {/*handle*/} );

function myCustomAsyncFunction() {
  
  // do an async operation
  // and when finished :
  
  return("customResult");
}

The previous snippet leads to an error : myCustomAsyncFunction doesn't have a property .then() attached to it.

Question : how can I properly and efficiently make my function a part of the "promise chain" ?


ANSWER :


In the promise world, an asynchronous function returns a promise instead of the customResult you are thinking of.

If you do not know what a deferred object and its attached promise are, a good video explaining the principles of promises can be found here.

Now, let's assume you have grasped the basic concepts. If we want our customFunction to return a promise, we have to build it, following this good tutorial :

var myCustomPromise = new Promise(function(resolve, reject) {
  
  // the async code of myCustomFunction

  if (/* everything turned out fine */) {
    resolve("someResult");
  }
  else {
    reject(Error("someError"));
  }
});

The new promise will immediately run the anonymous function you specify as a parameter. The promise object will then "wait" for the anonymous function to call either resolve or reject. Those two functions are triggers :

  • if resolve("someResult") is called by your code, any .then() attached to the promise will fire, and take "someResult" as the value to pass down the chain.
  • if reject(Error("someError")), the .catch() will fire...

All right, this is fun, but declaring a new promise fires my async code immediately. If I want to fire it at will, I must wrap all of the above in a function :

function myCustomFunction() { 
  
    return new Promise( function(resolve, reject) { 
       
        // the async code of myCustomFunction

        if (/* everything turned out fine */) {
            resolve("someResult");
        }
        else {   
            reject(Error("someError"));
        }   
    }); 
}

Here is the expected chain of events with this code :

  1. Whenever called, myCustomFunction will immediately return a new pending promise.
  2. This brand new pending promise will fire immediately your async code.
  3. At some point, your async code should call either resolve() or reject().
  4. This will give the promise its final status and value.
  5. Any .then() or .catch() listening to the promise will know what to do !
Community
  • 1
  • 1
klonaway
  • 449
  • 3
  • 18
  • 1
    `function myAsync() { return new Promise( function(fulfill, reject ) { /* your code */ fulfill( someVariable ); } ) }` – Sirko Aug 01 '16 at 14:52
  • 1
    Alternative existing question/answer which is more code oriented: http://stackoverflow.com/questions/33051270/promises-basics-how-to-promisify-async-node-code – Gimby Aug 01 '16 at 14:56
  • @Quentin : The duplicate you link to basically links to the documentations. I have already tried reading most of those pages and I think they are very unwelcoming for beginners. I asked this question this way also because I think it could speed up future beginners. I am ready to answer the question myself for others. – klonaway Aug 01 '16 at 15:21
  • @KLôN — It's still a duplicate even if you don't like the answers. You can give a better answer on the duplicate question if you like. – Quentin Aug 01 '16 at 15:21

0 Answers0