Consuming Promises
Promises are one approach to asynchronous programming. Functions which perform asynchronous operations (such as interacting with the file system or a database) can return a promise which is then resolved later. If that promise can't be kept (something is rejected) we can catch the error and deal with it.
then and catch
getDataFromFile().then((result) => {doSomethingWithData(result)}).catch((err) => {handleError(err)})
This example is about as simple as it gets. We don't need to understand the exact details of how to return a promise in order to use getDataFromFile. We just need to expect that:
The
thenfunction will calldoSomethingWithDataif there is no error.doSomethingWithDatacan be passed a value.The
catchfunction will callhandleErrorif there is an error, andhandleErrorwill be passed an error (often a JavaScriptErrorobject).
If getDataFromFile returns a resolved promise, then will be called (and catch won't be). If it returns a rejected promise, catch will be called (and then won't be).
If you are familiar with callbacks, you'll notice it's like a callback that has had the err and the data handling parts separated. The same thing might be written like this with callbacks:
getDataFromFileCallback(function(err, data) {if (err) {console.error(err.message)} else {console.log(data)}})
Promise chains
We can also string together quite long 'promise chains' which define the order certain tasks should occur in:
getDataFromFile().then((uncheckedMessyData) => {return checkTheData(uncheckedMessyData)}).then((messyData) => {return modifyTheData(messyData)}).then((tidyData) => {displayTheData(tidyData)}).catch((err) => {handleError(err)})
So long as each function in the chain returns a data object, this will help ensure everything takes place in the correct order. For example, displayTheData always gets called after modifyTheData.