[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 :
- Whenever called,
myCustomFunction
will immediately return a new pending promise. - This brand new pending promise will fire immediately your async code.
- At some point, your async code should call either
resolve()
orreject()
. - This will give the promise its final status and value.
- Any .then() or .catch() listening to the promise will know what to do !