Skip to content

Instantly share code, notes, and snippets.

@gihrig
Created June 18, 2015 05:05
Show Gist options
  • Save gihrig/1764bba1d0fc040cb9d4 to your computer and use it in GitHub Desktop.
Save gihrig/1764bba1d0fc040cb9d4 to your computer and use it in GitHub Desktop.
Bhavr Delgtn Ex4
/*
YDKJS Async and Performance ch 4:Generators "Delegating Asynchrony" pg 163
Delegating Asynchrony
Continuing the earlier multiple sequential Ajax requests
example, with yield-delegation:
This code is less than optimum as the first two requests are
called sequentially. They should be called concurrently.
See: gen-6-Concurrency.js
*/
'use strict';
/*
Generator runner utility
*/
function run(gen) {
var args = [].slice.call(arguments, 1), it;
// initialize the generator in the current context
it = gen.apply(this, args);
// return a promise for the generator completing
return Promise.resolve()
.then(function handleNext(value) {
// run to the next yielded value
var next = it.next(value);
return (function handleResult(next) {
// generator has completed running?
if (next.done) {
return next.value;
}
// otherwise keep going
return Promise.resolve(next.value)
.then(
// resume the async loop on
// success, sending the resolved
// value back into the generator
handleNext,
// if `value` is a rejected
// promise, propagate error back
// into the generator for its own
// error handling
function handleErr(err) {
return Promise.resolve(
it.throw(err)
)
.then(handleResult);
}
);
})(next);
});
}
// Promise returning Ajax call mock function
function request(url) {
return new Promise(function (resolve) {
setTimeout(function () {
var a = url.match(/v=(\d+)$/)[1]
console.log('requesting: ' + url + ' returned: ' + a);
resolve(a);
}, 1000);
});
}
// Demonstration code - Serial execution
function *foo() {
var r2 = yield request('http://some.url/?v=2');
var r3 = yield request('http://some.url/?v=3');
return [r2, r3]; // return the result of both request calls
}
function *bar() {
var r1 = yield request('http://some.url/?v=1');
var r3 = yield *foo(); // generator-delegation
console.log('*bar returned: ' + r1 + ',' + r3);
}
run(bar);
// requesting: http://some.url/?v=1 returned: 1 Notice that these
// requesting: http://some.url/?v=2 returned: 2 complete serially
// requesting: http://some.url/?v=3 returned: 3
// *bar returned: 1,2,3
// =========================================
// Demonstration code - Concurrent execution
function *foo(param) {
// make first two requests concurrently
var p1 = request(param[0]);
var p2 = request(param[1]);
// wait until both promises resolve
var r1 = yield p1;
var r2 = yield p2;
return [r1, r2]; // return the result of both request calls
}
function *bar() {
var r1 = yield *foo(['http://some.url/?v=1', 'http://some.url.2/?v=2']); // generator-delegation
var r2 = yield request('http://some.url/?v=3');
console.log('*bar returned: ' + r1 + ',' + r2);
}
run(bar);
// requesting: http://some.url/?v=1 returned: 1 Notice that these
// requesting: http://some.url/?v=2 returned: 2 complete concurrently
// requesting: http://some.url/?v=3 returned: 3
// *bar returned: 1,2,3
// =========================================
/*
See gen-5-Generators+Promises.js for ES7 async function/await.
Removes dependency on run() utility.
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment