Last active
January 13, 2019 16:39
-
-
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)
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
/** | |
* 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