Last active
February 27, 2020 22:34
-
-
Save gvergnaud/29b3520f8a176904313ff935434bf683 to your computer and use it in GitHub Desktop.
A `batch` function to batch several IOs together to gain in performance with the same api as if you were doing one IO at a time.
This file contains 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
import { debounce } from 'lodash'; | |
class Deferred { | |
constructor() { | |
this.promise = new Promise((resolve, reject) => { | |
this.resolve = resolve | |
this.reject = reject | |
}) | |
} | |
} | |
// just like debounce but returns a promise that resolves with the returned value of `f` | |
// debouncePromise :: (a -> Promise b) -> Number -> a -> Promise b | |
const debouncePromise = (f, ms) => { | |
let deferreds = []; | |
const debounced = debounce(args => { | |
const x = f(...args); | |
for (const deferred of deferreds) deferred.resolve(x); | |
deferreds = []; | |
}, ms); | |
return (...args) => { | |
const deferred = new Deferred(); | |
deferreds.push(deferred); | |
debounced(args); | |
return deferred.promise; | |
}; | |
}; | |
// batch | |
// :: ([a] -> b) | |
// -> Number? | |
// -> [a] | |
// -> Promise b | |
export const batch = (f, ms = 50) => { | |
let argumentsSet = new Set(); | |
const debounced = debouncePromise(() => { | |
const list = [...argumentsSet]; | |
argumentsSet.clear(); | |
return f(list); | |
}, ms); | |
return xs => { | |
for (const x of xs) argumentsSet.add(x); | |
return debounced(); | |
}; | |
}; |
This file contains 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
import { batch } from './batch' | |
const getSeveralUsers = batch(userIds => | |
fetch(`${someApi}/users?ids=${usersIds.join(',')}`).then(res => res.json()) | |
) | |
const getUser = id => getSeveralUsers([id]).then(users => users.find(u => u.id === id)) | |
// all this calls will be batched into one! | |
getUser(1).then(user1 => console.log(user1)) | |
getUser(2) | |
getUser(3) | |
getUser(4) | |
getUser(5) | |
getUser(6) | |
// => it will result in a single getSeveralUsers([1, 2, 3, 4, 5, 6]) function call |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment