Basics
Define a promise
Add a .then callback to a promise
Add a .catch callback to a promise
Wrap a setTimeout call in a promise
Nested Async Callbacks
var counter = 0;
setTimeout(function() {
counter++;
console.log("Counter:", counter);
setTimeout(function() {
counter++;
console.log("Counter:", counter);
setTimeout(function() {
counter++;
console.log("Counter:", counter);
}, 3000);
}, 2000);
}, 1000);
Console:
Counter: 1
Counter: 2
Counter: 3
Disadvantages of Nested Callbacks
The code is hard to read
Logic is difficult to reason about
The code is not modular
Promise: Conceptually
A promise is an object that represents a task that will be completed in the future
Analogy: Taking an number at a government office before you can get helped. The piece of paper you get is like your promise. The help you get at the counter is like the invocation of your callback.
Creating a Promise
var p1 = new Promise(function(resolve, reject) {
resolve([1,2,3,4]);
});
p1.then(function(arr) {
console.log("Promise p1 resolved with data:", arr);
});
Console:
Promise p1 resolved with data: [1,2,3,4]
Promise: Handling Errors
var p1 = new Promise(function(resolve, reject) {
reject("ERROR");
});
p1.then(function(data) {
console.log("Promise p1 resolved with data:", data);
}).catch(function(data) {
console.log("Promise p1 was rejected with data:", data);
});
Console:
Promise p1 was rejected with data: ERROR
Promise:
With Randomly Occurring Errors
var p1 = new Promise(function(resolve, reject) {
var num = Math.random();
if (num < 0.5) {
resolve(num);
} else {
reject(num);
}
});
p1.then(function(result) {
console.log("Success:", result);
}).catch(function(error) {
console.log("Error:", error);
});
Wrap setTimeout With Promise
var promise = new Promise(function(resolve, reject) {
setTimeout(function() {
var randomInt = Math.floor(Math.random() * 10);
resolve(randomInt);
}, 4000);
});
promise.then(function(data) {
console.log("Random int passed to resolve:",
data);
});
Returning a Promise:
Promise Chaining
var promise = new Promise(function(resolve, reject) {
setTimeout(function() {
randomInt = Math.floor(Math.random() * 10);
resolve(randomInt);
}, 500);
});
promise.then(function(data) {
console.log("Random int passed to resolve:",
data);
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve(Math.floor(Math.random() * 10));
}, 3000);
});
}).then(function(data) {
console.log("Second random int passed to resolve:",
data);
});
Promise Chaining:
Returning Data
var promise = new Promise(function(resolve, reject) {
resolve(5);
});
promise.then(function(data) {
return data * 2;
}).then(function(data) {
return data + 20;
}).then(function(data) {
console.log(data);
});
Console:
30
Nested Callbacks:
To Be Refactored
var counter = 0;
setTimeout(function() {
counter++;
console.log("Counter:", counter);
setTimeout(function() {
counter++;
console.log("Counter:", counter);
setTimeout(function() {
counter++;
console.log("Counter:", counter);
}, 3000);
}, 2000);
}, 1000);
Console:
Counter: 1
Counter: 2
Counter: 3
Step 1:
Create a Function Declaration
var counter = 0;
function incCounter() {
counter++;
console.log("Counter:", counter);
}
Step 2:
Create a runLater Function
var counter = 0;
function incCounter() {
counter++;
console.log("Counter:", counter);
}
function runLater(callback, timeInMs) {
var p = new Promise(function(resolve, reject) {
setTimeout(function() {
var res = callback();
resolve(res);
}, timeInMs);
});
return p;
}
Step 3: Chain Promises
var counter = 0;
function incCounter() {
counter++;
console.log("Counter:", counter);
}
function runLater(callback, timeInMs) {
var p = new Promise(function(resolve, reject) {
setTimeout(function() {
var res = callback();
resolve(res);
}, timeInMs);
});
return p;
}
runLater(incCounter, 1000).then(function() {
return runLater(incCounter, 2000);
}).then(function() {
return runLater(incCounter, 3000);
}).then(function() {
// final .then not necessary
});
Promise Refactor: Side By Side
var counter = 0;
function incCounter() {
counter++;
console.log("Counter:", counter);
}
function runLater(callback, timeInMs) {
var p = new Promise(function(resolve, reject) {
setTimeout(function() {
var res = callback();
resolve(res);
}, timeInMs);
});
return p;
}
runLater(incCounter, 1000).then(function() {
return runLater(incCounter, 2000);
}).then(function() {
return runLater(incCounter, 3000);
});
var counter = 0;
setTimeout(function() {
counter++;
console.log("Counter:", counter);
setTimeout(function() {
counter++;
console.log("Counter:", counter);
setTimeout(function() {
counter++;
console.log("Counter:", counter);
}, 3000);
}, 2000);
}, 1000);
It is useful to understand how promises work (resolve, reject), but in practice you will often use promises that are returned to you
Promises In Practice