Describe the disadvantages of using nested callbacks
Return a promise from a .then callback function
Use a promise to make asynchronous code seem sequential
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
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