JavaScript Promises
@tejesh95
Tejesh P
Synchronous Code
Synchronous Requests block the execution of code which creates "freezing" on the screen and an unresponsive user experience.
Reference: MDN Synchronous_and_Asynchronous_Requests
But I know how to use callbacks ...
Nested code impacts readability in negative way
Nested code impacts readability in negative way
CallBack Hell
Escape from callback hell...?
Stay away from anonymous functions
var form = document.querySelector('form')
form.onsubmit = function (submitEvent) {
var name = document.querySelector('input').value
request({
uri: "http://example.com/upload",
body: name,
method: "POST"
}, function (err, response, body) {
var statusMessage = document.querySelector('.status')
if (err) return statusMessage.value = err
statusMessage.value = body
})
}
var form = document.querySelector('form')
form.onsubmit = function formSubmit (submitEvent) {
var name = document.querySelector('input').value
request({
uri: "http://example.com/upload",
body: name,
method: "POST"
}, function postResponse (err, response, body) {
var statusMessage = document.querySelector('.status')
if (err) return statusMessage.value = err
statusMessage.value = body
})
}
Stay away from anonymous functions
Stay away from anonymous functions
document.querySelector('form').onsubmit = formSubmit
function formSubmit (submitEvent) {
var name = document.querySelector('input').value
request({
uri: "http://example.com/upload",
body: name,
method: "POST"
}, postResponse)
}
function postResponse (err, response, body) {
var statusMessage = document.querySelector('.status')
if (err) return statusMessage.value = err
statusMessage.value = body
}
Promises
Promises are a way to write async code that still appears as though it is executing in a top-down way,
and
handles more types of errors due to encouraged use of try/catch style error handling.
Promises
Promises - Can be created from constants
var value = 10;
var promiseForValue = Promise.resolve(value);
// equivalent to
var promiseForValue = new Promise(function (fulfill) {
fulfill(value);
});
JQuery $.ajax is a promise
var jQueryPromise = $.ajax('/ajax-endpoint');
var realPromise = Promise.resolve(jQueryPromise);
// equivalent to
var realPromise = new Promise(function (fulfill, reject) {
jQueryPromise.then(fulfill, reject);
});
Rejected Promises creation
var rejectedPromise = Promise.reject(new Error('Whatever'));
// equivalent to
var rejectedPromise = new Promise(function (fulfill, reject) {
reject(new Error('Whatever'));
});
But I know how to use callbacks ...
can still be optimized further!
Promise.all( )
Promise.all( )
var template_urls = [
'./templates/main.template.html',
'./templates/stages.template.html',
'./templates/data_loader.template.html',
'./templates/data_mapper.template.html',
'./templates/customize_chart.template.html',
'./templates/publish_embed.template.html',
'./templates/layer_list.template.html',
'./templates/property_list.template.html',
'./templates/property_detail.template.html',
'./templates/input.template.html',
'./templates/mark.template.html',
'./templates/select.template.html',
'./templates/color_schemes.template.html',
'./templates/padding.template.html',
'./templates/tooltip.template.html',
'./templates/external_url.template.html'
]
Promise.all(
template_urls.map(function(url) {
return fetch(url)
})
)
.then(function(responses) {
return Promise.all(
responses.map(function(res) {
return res.text()
})
)
})
.then(function(tmpls) {
....
....
Promise.all( )
function dependency_accumulator(current_template, self, data, options) {
if ($(current_template).data('subtemplates') === undefined) {
return Promise.resolve(100)
} else {
var dependency_selectors = $(current_template)
.data('subtemplates')
.split(',')
.filter(function (selector) {
return !$(selector).data(_compiled)
})
return Promise.all(
dependency_selectors.map(function (dependency_selector) {
return dependency_accumulator(dependency_selector, self, data, options)
})
).then(function () {
return Promise.all(
dependency_selectors.map(function (sub_temp_selector) {
return execute_render($(sub_temp_selector), data, options)
})
)
})
}
}
Promise.all( ) Gotchas!
var promise_calls = ['bar-vega.json', 'line-vega.json'].map(fetch)
Promise.all(promise_calls)
.done(function (results) {
// results is an array of the values stored
// in a.json and b.json
}, function (err) {
// If any of the files fails to be read,
// err is the first error
});
Promise.allSettled( )
Promise methods
.all - wait success of all, fail if just one
.allSettled(arr) - wait for all promises to settle (either with a value or with an error, doesnt matter)
.race(arr) - wait for 1 promise to succeed, fail if just a single one fails
.any(arr) - wait for success of 1, fail when impossible to fulfill 1 (only when everyone fails)
.some(arr, N) - wait success of N, fail when impossible to fulfill N (because arr.length - N + 1 have failed)
Bluebird Promise library supports
The goal is to cancel it if requestData succeeded. "There is a different UI active now and it would be pointless to try and process things further towards rendering"
Promise
.race([waitSomeRequest(), stillSameRoute()])
.then(renderDataFromRequest);
.race(arr) - wait for 1 promise to succeed, fail if just a single one fails
Error Handling using .catch()
function asyncTask(url) {
return new Promise((resolve, reject) => {
if (url) {
return setTimeout(() => {
resolve(asyncTask2());
}, 500);
}
reject({
error: 'url missing in async task 1'
});
});
}
function asyncTask2(url) {
return new Promise((resolve, reject) => {
if (url) {
return resolve({
id:2
});
}
reject({
error: 'url missing in async task 2'
});
});
}
asyncTask('google.com')
.catch(err => {
console.log('failed ', err); // { error: 'url missing in async task 2' }
return err;
});
Error Handling in Nested Promises
function asyncTask(url) {
return new Promise((resolve, reject) => {
if (url) {
return setTimeout(() => {
resolve(asyncTask2());
}, 500);
}
reject({
error: 'url missing in async task 1'
});
});
}
function asyncTask2(url) {
return new Promise((resolve, reject) => {
if (url) {
return resolve({
id:2
});
}
reject({
error: 'url missing in async task 2'
});
});
}
asyncTask('google.com')
.catch(err => {
console.log('failed ', err); // { error: 'url missing in async task 2' }
return err;
});
Error Handling in Promises
// covers promise constructor in asyncTask and 3 then
asyncTask()
.then()
.then()
.then()
.catch()
asyncTask()
.catch() // only covers promise constructor in asyncTask
.then()
.then()
.catch() // 2 then
Thank you!
Questions?
JS Promises
By Tejesh P
JS Promises
- 81