Viktor Shevchenko
Web developer from Kyiv
vict.shevchenko@gmail.com
@vict_shevchenko
//sync
function a () { // returns 'a' }
function b () { // returns 'b' }
function c () { // returns 'c' }
a();
b();
c();
// a
// b
// c
//async
function a () { // returns 'a' }
function b () { // returns 'b' }
function c () { // returns 'c' }
a();
b();
c();
// a
// c
// b
Why we want to use it at all?
So what will happen if we will run them synchronous?
console.log('hello'); //a
setTimeout(function () {
console.log('to Lviv'); //b
}, 1000);
console.log('from Kyiv') //c
//hello
//from Kyiv
//to Lviv
setTimeout(function () {
console.log('hello Lviv');
}, 1000);
for(var i = 0; i < 100000000; i++) {
//calculate Fibonacci ~5sec
}
//hello Lviv (after much more than 1sec)
console.time('test');
setTimeout(function() {
console.log(console.timeEnd('test'));
}, 0);
// test: 4.319ms
function getY() {
var y;
$.get('get/y', function(result) {
y = result;
});
return y;
}
var x = 10;
var y = getY();
console.log(x + y);
// NaN
Why it does not work?
Because JS allows to to pass functions as a parameters, we can wrap a code in a callback
function getY(callback) {
var y;
$.get('get/y', function(result) {
y = result; //5
callback(y);
});
}
var x = 10;
getY(function(y) {
console.log(x + y);
});
//15
function updateStoryComment(id) {
$.get({
url: 'get/story/id',
success: function (story){
$.get({
url: 'get/story/comment/:id',
success: function (comment) {
asyncUserDialog(function (updatedText) {
$.post({
url: 'post/story/comment/id',
data: updatedText,
success: function () {
notifyUser();
}
});
});
}
});
}
});
}
updateStoryComment(12);
WIKI: In computer science, future, promise, and delay refer to constructs used for synchronizing in some concurrent programming languages. They describe an object that acts as a proxy for a result that is initially unknown, usually because the computation of its value is yet incomplete.
Abstraction over asynchronous code
Utility on callback aggreagation
function asyncSum(a, b) {
var promise = new Promise();
setTimeout(function() {
promise.resolve(a + b);
}, 1000);
return promise;
}
function () {
var asyncResult = asyncSum(3,5);
asyncResult.then(function (result) {
console.log(result);
asyncResult.catch(function (error) {
console.log(error);
asyncResult.finally(function (error) {
console.log("Fully Done Now");
}
Library usage
function asyncSum(a, b) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve(a + b);
}, 1000);
});
}
var asyncResult = asyncSum(3,5); // returned result is promise object
asyncResult.then(function (result) {
console.log(result); //logs 8 after more that 1000ms
});
Native usage
function updateStoryComment(id) {
fetch('get/story/id')
.then(function (story) {
return fetch('get/story/comment/id');
})
.then(asyncUserDialog())
.then(function (updatedText) {
return fetch('get/story/comment/id', method: 'POST', body: updatedText);
})
.then(function () {
notifyUser();
})
.catch(handleErrorDuringUpdating());
}
updateStoryComment(12);
Provide you with async version of return and throw
var result, exception = false;
try {
result = doSomethingSync();
} catch (ex){
exception = ex;
handle(exception)
}
if(!exception) {
return result;
}
doSomethingAsync()
.then(processResult, handleException);
Sync
Async
15.02.2008
The first widespread use of this pattern was with the dojo toolkit deferred object in version 0.9.
24.03.2009
31.12.2011
jQuery introduced a new concept in version 1.5 called Deferred which is also a derivative implementation of the CommonJS Promises/A proposal.
... so Domenic Denicola got angry and wrote
...and he made https://github.com/domenic/promise-tests
.then(appearedAfterFewMonth)
function someAsyncFunction () {
return new Promise(function (resolve, reject) {
//all async staff goes her
if(all is well) {
resolve('Hurray');
} else {
reject('Something went wrong');
}
});
}
someAsyncFunction()
.then(function (result) {
console.log(result) //Hurray
}, function (error) {
console.log(error) //Something went wrong
});
1. Chose a library (most popular are)
2. If you see a jQuery promise - wrap it!
var realPromise = Q(jQueryPromise)
3. Keep sync/async paralel in mind
4. Promises are not:
Wouldn't it be nice, that when you execute your function, you could pause it at any point, calculate something else, do other things, and then return to it, even with some value and continue?
Designed for iteration work
Solution of writing asynchronous code with generators is based on possibility to make a non-blocking pause and wait (yield) until Promise will be resolved
function * updateStoryComment(id) {
try {
var story = yield fetch('get/story/id');
var comment = yield fetch('get/story/comment/id');
var updatedText = yield asyncUserDialog();
yield fetch('get/story/comment/id', method: 'POST', body: updatedText);
} catch (ex) {
handleErrorDuringUpdating()
}
}
var generator = updateStoryComment(12);
generator.next().value.then(function (story) { // { value: resolvedPromise, done: false }
return generator.next(story).value;
}).then(function (comment) {
return generator.next(comment).value;
}).then(function (updatedText) {
return generator.next(updatedText).value;
}).then(function (){
notifyUser();
});
var co = require('co');
function updateStoryComment(id) {
return co(function * updateStoryComment() {
try {
var story = yield fetch('get/story/id');
var comment = yield fetch('get/story/comment/id');
var updatedText = yield asyncUserDialog();
yield fetch('get/story/comment/id', method: 'POST', body: updatedText);
} catch (ex) {
handleErrorDuringUpdating()
}
});
}
updateStoryComment(12).then(function() {
notifyUser()
});
Under the hood async functions using Promises - this is why the async function will return with a Promise.
async function updateStoryComment(id) {
try {
var story = await fetch('get/story/id');
var comment = await fetch('get/story/comment/id');
var updatedText = await asyncUserDialog();
await fetch('get/story/comment/id', method: 'POST', body: updatedText);
notifyUser();
} catch (ex) {
handleErrorDuringUpdating()
}
}
updateStoryComment(12);
You have to put the async keyword before the function declaration. After that, you can use the await keyword inside your newly created async function
Async / Await is amazing, the mecca of working with asynchronous code in JavaScript. Personally I think it’s a shame we got Generators in ES6 instead of this. The solution is so eloquent that it will forever change the way we write JavaScript.
By Viktor Shevchenko
how to write async js code