jskatas.org Continuously Learn JavaScript. Your Way.

Promise: chaining then()

Chaining promises can enhance readability of asynchronous code.

chaining multiple promises can enhance readability

a function given to then() fulfills (if it doesnt throw)
//: {"jskatas": {"runnerOptions": {"topLevelAwait": true}}} const beNice = () => { throw new Error('I am nice') }; const promise = Promise.resolve() .then(beNice); assert.equal(await promise, 'I am nice');

chain promises

then() receives the result of the promise it was called on
//: {"jskatas": {"runnerOptions": {"topLevelAwait": true}}} const removeMultipleSpaces = s => s.replace(/\s+/g, ' '); const wordsPromise = Promise.resolve('one space between each word'); const promise = wordsPromise .then(s => removeMultipleSpaces()) assert.equal(await promise, 'one space between each word')
multiple then()s can be chained
//: {"jskatas": {"runnerOptions": {"topLevelAwait": true}}} const appendPeriod = s => `${s}.`; const removeMultipleSpaces = s => s.replace(/\s+/g, ' '); const wordsPromise = Promise.resolve('Sentence without an end'); const promise = wordsPromise .then(removeMultipleSpaces); assert.equal(await promise, 'Sentence without an end.');
order of the then()s matters
//: {"jskatas": {"runnerOptions": {"topLevelAwait": true}}} const trim = s => s.replace(/^\s+/, '').replace(/\s+$/, ''); const appendPeriod = s => `${s}.`; const removeMultipleSpaces = s => s.replace(/\s+/g, ' '); const wordsPromise = Promise.resolve('Sentence without an end '); const promise = wordsPromise .then(appendPeriod) .then(trim) .then(removeMultipleSpaces); assert.equal(await promise, 'Sentence without an end.');
any of the things given to then() can resolve asynchronously (the real power of Promises)
//: {"jskatas": {"runnerOptions": {"topLevelAwait": true}}} const appendPeriod = s => `${s}.`; const asyncUpperCaseStart = (s, onDone) => { const format = () => onDone(s[0].toUpperCase() + s.substr(1)); setTimeout(format, 10); }; const wordsPromise = Promise.resolve('sentence without an end'); const promise = wordsPromise .then(s => new Promise(resolve => asyncUpperCaseStart)) .then(s => new Promise(resolve => setTimeout(() => resolve(appendPeriod(s)), 10))); assert.equal(await promise, 'Sentence without an end.')
also asynchronously, the order still matters, promises wait, but don`t block
//: {"jskatas": {"runnerOptions": {"topLevelAwait": true}}} const appendPeriod = s => `${s}.`; const asyncUpperCaseStart = (s, onDone) => { const format = () => onDone(s[0].toUpperCase() + s.substr(1)); setTimeout(format, 10); }; const trim = s => s.replace(/^\s+/, '').replace(/\s+$/, ''); const wordsPromise = Promise.resolve('trailing space '); const promise = wordsPromise .then(s => new Promise(resolve => asyncUpperCaseStart(s, resolve))) .then(s => new Promise(resolve => setTimeout(() => resolve(appendPeriod(s)), 10))) .then(s => new Promise(resolve => setTimeout(() => resolve(trim(s)), 10))) assert.equal(await promise, 'Trailing space.');

Links

The description of how a value given to `then()` becomes a resolved promise.
Looks like the description in the spec of what `then()` accepts and does with the given value.
A long article introducing promises.

Required Knowledge

Related Katas

Promise

Difficulty Level

ADVANCED

First Published

10 November 2015

Stats

6 tests to solve