Skip to content

Instantly share code, notes, and snippets.

@deepakshrma
Last active January 13, 2019 16:39
Show Gist options
  • Save deepakshrma/1a899bf49ccb77d3b5be771907b32e4c to your computer and use it in GitHub Desktop.
Save deepakshrma/1a899bf49ccb77d3b5be771907b32e4c to your computer and use it in GitHub Desktop.
JS_Problem_1: Read files in parallel and print result sequentially(Async Thunk/Promise Pattern: JS Advance)
/**
* Fake read file function
* @param {*} name : name of file to read
* @param {data} cb : content of the file
*/
const readFile = (type, name, cb) => {
const time = Math.floor(Math.random() * 10 * 1000);
const fn = cb.bind(null, `{ type: ${type}, name: ${name}, data: "${name + '_' + time}ms"}`);
console.log(`fetching file: ${name} of ${type} in ${time}ms...`)
setTimeout(fn, time)
}
const files = ['text1.js', 'text2.js', 'text3.js']
/**
* Problem: 1
* Call readFile funtion with 3 filename(text1, text2, text3) in parallel. Print result in sequence(output of text1, text2 and text3 in end).
* Output:
* { name: test1.js, data: "test1.js_811ms"}
* { name: test2.js, data: "test2.js_6639ms"}
* { name: test3.js, data: "test3.js_3940ms"}
*/
// Solution 1: Using global array of values
const responses = [];
const countDone = () => responses.filter(x => x === false).length
console.time("NORMAL: TOTAL_TIME")
const handleResponse = (filename, data) => {
if (!responses[filename]) responses[filename] = data;
files.forEach((name, index) => {
if (typeof responses[index] === 'undefined') {
return
}
if (typeof responses[index] !== 'boolean') {
console.log(responses[index])
responses[index] = false
return
}
})
if (countDone() === files.length) console.timeEnd("NORMAL: TOTAL_TIME")
}
readFile('normal', files[0], handleResponse.bind(null, 0))
readFile('normal', files[1], handleResponse.bind(null, 1))
readFile('normal', files[2], handleResponse.bind(null, 2))
// Solution 2: Using thunk pattern
const getFileThunk = (name) => {
let data, fn;
readFile('thunk', name, (respons) => {
if (fn) return fn(respons);
else data = respons;
})
return function done(cb) {
if (data) return cb(data);
else fn = cb;
}
}
console.time("THUNK: TOTAL_TIME")
const thunk1 = getFileThunk(files[0])
const thunk2 = getFileThunk(files[1])
const thunk3 = getFileThunk(files[2])
thunk1((res) => {
console.log(res)
thunk2((res) => {
console.log(res)
thunk3((res) => {
console.log(res)
console.timeEnd("THUNK: TOTAL_TIME")
})
})
})
// Solution 3.1: Using promise
const promiseReadFile = (name) => {
return new Promise((resolve, _) => {
readFile('promise', name, resolve)
})
}
const p1 = promiseReadFile(files[0])
const p2 = promiseReadFile(files[1])
const p3 = promiseReadFile(files[2])
console.time("PROMISE: TOTAL_TIME")
p1
.then(console.log)
.then(() => p2)
.then(console.log)
.then(() => p3)
.then(console.log)
.then(console.timeEnd.bind(null, "PROMISE: TOTAL_TIME"))
// Solution 3.2: Using promise accumulator
console.time("PROMISE-V2: TOTAL_TIME")
files
.map(promiseReadFile)
.reduce((chain, pr) => {
return chain.then(() => pr)
.then(console.log)
}, Promise.resolve())
.then(console.timeEnd.bind(null, "PROMISE-V2: TOTAL_TIME"))
// Solution 3.3: Using promise all
Promise.all(files.map(promiseReadFile))
.then((responses) => {
responses.forEach(console.log)
console.timeEnd("PROMISE: TOTAL_TIME")
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment