Last active
April 13, 2018 08:31
-
-
Save lqt0223/da7e77fcf575b86175a6d2b189d7cf9c to your computer and use it in GitHub Desktop.
17 Running asynchronous jobs in sequence (without paralleling) - A Promise based implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Running asynchronous jobs in sequence (without paralleling) | |
// A Promise based implementation | |
// The 'sequence' function receive an array and an iteratee as parameters. | |
// The iteratee is a function that returns a promise. | |
// You should incapsulate your desired asynchronous job in this function. | |
// The array is the parameters for the iteratee function in order. | |
// The 'sequence' function returns a promise to make it thenable. | |
// The promise will resolve all results of asynchronous jobs in an array, | |
// or reject any error when occured. | |
// The 'sequence2' function is a variadic version of 'sequence' | |
// The iteratee will be the first argument and the rest arguments will be used as arguments invoked by iteratee | |
// The 'sequence3' function is an alternation of 'sequence2' in that | |
// it will continue job execution when there is a error in the middle. | |
// The promise will resolve a 2-dimensional array containing all succeeded job results and failed job errors. | |
// Below is an example of sending http requests once at a time. | |
const request = require('request') | |
function getPost(id) { | |
return new Promise((resolve, reject) => { | |
request('https://jsonplaceholder.typicode.com/posts/' + id, (error, response, body) => { | |
if (error) { | |
reject(error) | |
} else { | |
console.log(body) | |
resolve(body) | |
} | |
}) | |
}) | |
} | |
sequence([1, 2, 3, 4, 5], getPost).then((results) => { | |
console.log(results.length) | |
console.log(results[0]) | |
}).catch((err) => { | |
console.log(err, 'here') | |
}) | |
// The implementation... | |
function sequence(arr, iteratee) { | |
var results = [] | |
return new Promise((resolve, reject) => { | |
(function tick() { | |
if (arr.length > 0) { | |
iteratee(arr.shift()).then((result) => { | |
results.push(result) | |
tick() | |
}).catch((err) => { | |
reject(err) | |
}) | |
} else { | |
resolve(results) | |
} | |
})() | |
}) | |
} | |
function sequence2(iteratee, ...arglists) { | |
var results = [] | |
return new Promise((resolve, reject) => { | |
(function tick(){ | |
var args = arglists.map((list) => { | |
return list.shift() | |
}) | |
if (!args.every((e) => Object.is(e, undefined))) { | |
iteratee.apply(null, args).then((result) => { | |
results.push(result) | |
tick() | |
}).catch((err) => { | |
reject(err) | |
}) | |
} else { | |
resolve(results) | |
} | |
})() | |
}) | |
} | |
function sequence3(iteratee, ...arglists) { | |
var results = [] | |
var errors = [] | |
return new Promise((resolve, reject) => { | |
(function tick(){ | |
var args = arglists.map((list) => { | |
return list.shift() | |
}) | |
if (!args.every((e) => Object.is(e, undefined))) { | |
iteratee.apply(null, args).then((result) => { | |
results.push(result) | |
tick() | |
}).catch((err) => { | |
errors.push(err) | |
tick() | |
}) | |
} else { | |
resolve([results, errors]) | |
} | |
})() | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment