JavaScript Promises
Taming Async flow
Motivation
Solution to "callback hell"
Common Promise example
Basics
Use
Create
Flow
Promises
Basics
Basics
What are promises?
Promises are an alternative way to manage your asynchronous code in JavaScript.
Basics
What are promises?
a promise is an object who represents the result of an asynchronous operation.
It is a place holder for a value that will become available in the future.
Implementation status
Basics
Spec
Standard Libraries
Full list
Basics
Promises Axiomas
-
Will always be Async
Executed at least on the next tick / frame -
a Promise handler always return another Promise
-
Promises can be used only once
Basics
Promises states
-
PENDING - The initial state of a promise.
-
RESOLVED - a successful operation - returns a Value.
-
REJECTED - a failed operation - throws an exception.
has a 'Reason' property. -
(SETTLED) - means either resolved or rejected
Once a promise is settled, it is immutable
and cannot be changed.
Basics
Using
Promises
Promise.prototype.then( )
Use
get_user(id)
.then(on_resolved, on_rejected)
get_user(862726)
.then(user_data => console.log(user_data) //success...
,err => console.error(err.message)) //failure...
Chaining Promises
Use
"a Promise handler always return another Promise"
therefore it can be chained to other Promises
get_user(id)
.then(on_resolved_1, on_rejected_1)
.then(on_resolved_2)
.then(null, on_rejected_2)
Promise.prototype.catch( )
Use
get_user(id)
.then(null, on_rejected)
get_user(id)
.catch(on_rejected)
Promise.prototype.catch( )
Use
get_user(id)
.then(step1)
.then(step2)
.then(step3)
.then(step4)
.catch( err => {
// The chain is broken and goes to the catch
// Handle any errors from all above steps
})
Chaining Promises( )
Promise.prototype.catch( )
Use
get_user(id)
.then(step1,on_get_user_reject)
.then(step2,on_step1_reject)
.then(step3,on_step2_reject)
.then(step4,on_step3_reject)
.catch( err => {
// The chain is NOT broken
// Handle any errors from step4
})
Chaining Promises( )
Creating
Promises
function get_user(id){
return new Promise((resolve, reject) => {
fetch(`https://somedomain.com/api/users/${id}`)
.then(response => response.json())
.then(user_data => {
if(user_data.active) resolve(user_data);
else reject(new Error('This user is not active any longer'))
//reject due to an application logical error
})
.catch(err => reject(err)) //reject due to a communication error
})
}
Create
new Promise( )
const fs = require('fs');
function readFile(filename, enc){
return new Promise((resolve, reject) => {
fs.readFile(filename, enc, (err, data) => {
if (err) reject(err);
else resolve(data);
})
})
}
Create
Promisification
const fs = require('fs');
const read_file = Promise.promisify(fs.readFile);
read_file("./path/to/myfile.js", "utf8")
.then( contents => console.log(`The content of myfile.js is: ${contents}`) )
.catch( err => console.log(`Error reading myfile.js ${err.message}` ));
Promise.promisify()
Create
const util = require('util');
const fs = require('fs');
const stat = util.promisify(fs.stat);
stat('./some/path')
.then( stats => {
// Do something with `stats`
}).catch( error => {
// Handle the error.
});
util.promisify()
Create
const fs = Promise.promisifyAll(require("fs"));
fs.readFileAsync("myfile.js", "utf8")
.then( contents => console.log(contents))
.catch(err => console.error(err.message) );
Promise.promisifyAll()
Create
Controll Async Code Flow
fetch('/api/friends')
.then(step1)
.then(step2)
.then(step3)
.then(step4)
.catch( err => {
// Handle any error from all above steps
})
Flow
Chaining Promises( )
var items = [0,1,2,3,4,5,6,7,8,9];
Promise.each(items, item => {
return Promise.delay(Math.random() * 2000)
.then(()=> console.log(`Finished item: ${item}`) );
})
.then( origin_array => {
console.log(`All tasks are done now... ${origin_array}`);
})
.catch( err =>
console.error(err.message)
});
Promise.each()
Serial iteration on a collection
and then...
Flow
var items = [0,1,2,3,4,5,6,7,8,9];
Promise.map(items, item => {
return Promise.delay(Math.random() * 2000)
.then(()=> {
console.log(`Finished item: ${item}`);
});
}, {concurrency: 3}) //adjust concurrency...
.then((resultValuesArray) => console.log('All tasks are done now...'))
.catch( err => console.error(err.message));
Promise.map()
Parallel iteration on a collection
and then...
Flow
Promise.all(pending_promises_Array)
.then( items => console.log('All operations are complete!', 'items: ',items))
.catch( err => console.error( err.message ) );
Promise.all()
Parallel execution of different async operations
and then...
- input - an array of promises
- output an array of results values
(ordered respectively to the original array order!)
Flow
Promise.props(pending_promises_obj)
.then( results => {
console.log('All operations are complete!, result: ');
console.dir(results);
})
.catch( err => {
console.error(err.message);
})
Promise.props()
Parallel execution of different async operations
and then...
- input - an Object with promises key/value pairs
- output - an Object of results key/values
(easier to work with results...)
Flow
Promise.race(pending_promises_Array)
.then( item => {
console.log(`The first operation is complete!, first item: ${item}`);
})
.catch( err => {
console.log(`Error: ${err.message}`);
})
Promise.race()
The .then( ) handler runs after the
first async operation is complete
Flow
Promise.some(pending_promises_Array, 2)
.spread( (first, second) => {
console.log(`first: ${first}, second: ${second}`)
})
.catch( err => {
console.log(`Error: ${err.message}`)
})
Promise.some()
Similar to race()
The .then() handler runs after the (n)th async operation is complete
Flow
Basics
Use
Create
Flow
JavaScript Promises
By Yariv Gilad
JavaScript Promises
Go through these slides to get a strong grip on JavaScript Promises. A way to manage your async JavaScript code.
- 3,872