Skip to content

Instantly share code, notes, and snippets.

@lqt0223
Last active April 13, 2018 08:31
Show Gist options
  • Save lqt0223/da7e77fcf575b86175a6d2b189d7cf9c to your computer and use it in GitHub Desktop.
Save lqt0223/da7e77fcf575b86175a6d2b189d7cf9c to your computer and use it in GitHub Desktop.
17 Running asynchronous jobs in sequence (without paralleling) - A Promise based implementation
// 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