Today we’re going to combine two of the most useful tools that a JavaScript developer has in his or her tool belt. and . Promises Function Composition Please enjoy this barely related comic about Functional Programming :) Promises The is a simple but powerful way to handle asynchronous operations. To create a promise you would type and the only argument would be a callback function. Promise API new Promise() The callback function accepts two arguments: and . When your asynchronous function finishes you call resolve with the result. If your asynchronous function throws an error you can call with that error. It looks like this: resolve reject reject const myPromise = new Promise((resolve, reject) => {setTimeout(() => {resolve('Hello World');}, 2000);}); myPromise.then(res => console.log(res)); // 'Hello World' is shown after 2 seconds. We are able to access the result of by calling , which receives a callback function that has whatever you called with as its argument. resolve Promise.prototype.then resolve Sometimes a Promise will throw an error. We can’t use a traditional block in this scenario, because the error may be thrown at a later time. Instead we use . Just like it receives a callback function. The difference is that it will receive whatever you pass to the argument. try/catch Promise.prototype.catch .then() reject Finally, we may want to do some cleanup. What do we use? You guessed it: . Finally accepts a callback function, but that callback accepts no arguments. You can count on this function to be called after your Promise chain is finished executing. At the time of this writing isn’t available everywhere. You can use it in the latest version of Chrome or in . Promise.prototype.finally finally Bluebird Chaining Promises When working with Promises you can chain them. This means when you have multiple asynchronous options in a row you can do them one after the other. It looks something like this: // In this example Promise.resolve represents any async action that returns a promise.new Promise(resolve => setTimeout(() => resolve(10), 3000)).then(res => Promise.resolve(res + 10)).then(res => Promise.resolve(res + 10)).then(console.log).catch(console.error).finally(() => console.log('All done!');// After 3 seconds logs 30// Then it logs 'All done!' As you can see Promises can be chained so that asynchronous operations can happen almost as if they are synchronous. We used to represent a function that returns a Promise. wraps a value in a Promise. Promise.resolve Promise.resolve This isn’t a bad way of working with Promises, but I think we can do better. Composition Function composition is simple, but can be hard to wrap your mind around at first. The entire point of composition is to allow you to string functions together. If we were to look at our last example, but with synchronous functions, it would look something like this: const result = compose(res => res + 10,res => res + 10,)(10);console.log(result); // 10 We took the result of each function, passed it to the next function, and that was the result of the whole composed function. That function isn’t assumed to be a global function, like or are. We’ll have to define it. To define compose we’d have something like this: compose Promise Promise.resolve const compose = (...functions) =>initialValue =>functions.reduceRight((sum, fn) => fn(sum),initialValue,); So.. what exactly is going on here? Let me walk you thought it step by step. This can be confusing, particularly if you aren’t familiar with a recent update to JavaScript known as . ES6 First we accept any amount of functions. Then we use the to gather all of those functions into a single array. spread operator Next we accept the initial value that our compose function will use as it’s initial argument. Once we have that initial value we begin calling each function from right to left (or bottom to top if you look at the example above). We use to make sure that the functions are called in this order. If you’re familiar with how works then you’re already familiar with reduceRight, you just may not know it! is reduce, but it works backwards. Array.prototype.reduceRight Array.prototype.reduce reduceRight The Array reduce and reduceRight methods iterate through an array, and at each index in the array a callback is called. That callback receives two arguments. A sum, and the value at the current index of the array. In our case the value at the current index is a function. The sum is the for the first function in the array. After that the sum is the result of the previous function that has been called with the results of the function before it. initialValue So now we hopefully see the power of Promises, the convenience and clarity of composition. What happens when we put them together? Composing Promises You might wonder why we can’t just compose Promises with the function that we just created. The problem is that we access that value through . So unless each of our functions unwraps it’s arguments like: compose Promise.then function myComposedFunction(argument) {argument.then(() => {// actual content of myComposedFunction goes here});} Then the function’s argument won’t be what it expects. Plus there’s another problem. Now will only work with Promises! We can solve that problem rather simply. myComposedFunction function myComposedFunction(argument) {Promise.resolve(argument).then(() => {// actual content of myComposedFunction goes here});} But this seems like a lot of . Particularly if this is supposed to be a simple function. Maybe it just does: we’ve just turned a very simple function into a very complicated one. boilerplate return argument + 10; A much better way is to handle this within the function itself. compose const composePromise = (...functions) =>initialValue =>functions.reduceRight((sum, fn) => Promise.resolve(sum).then(fn),initialValue); This function works exactly the same as our function earlier, with one major difference. It accepts Promises, and returns a Promise. You can use it like this: composePromise compose const add100ToNumberString = composePromise(console.log,res => res.toString(),res => Promise.resolve(res + 100),res => Promise.resolve(Number(res)),); add100ToNumberString(new Promise(resolve => {setTimeout(() => {resolve('400');}, 2000);}));// Eventually prints out '500' after 2 seconds You can continue to chain because the result of is a Promise. You can use and If needed as well! add100ToNumberString .catch() .finally() Try it yourself! Below I’ve embedded a playground with all this code in it so that you can try it out for yourself! Open up the console to see the results. CodePen Hi, I’m Justin Fuller. I’m so glad you read my post! I need to let you know that everything I’ve written here is my own opinion and is not intended to represent my employer in way. All code samples are my own, and are completely unrelated to Bank Of America’s code. any I’d also love to hear from you, please feel free to connect with me on , , or . Thanks again for reading! LinkedIn Github Medium