Skip to content

Instantly share code, notes, and snippets.

@yongjun21
Last active June 28, 2022 11:56
Show Gist options
  • Save yongjun21/ec0ea757b9dcbf972a351453755cadcb to your computer and use it in GitHub Desktop.
Save yongjun21/ec0ea757b9dcbf972a351453755cadcb to your computer and use it in GitHub Desktop.
Implement bluebird's Promise.map & Promise.filter with native Promise
Promise.map = function (iterable, mapper, options) {
options = options || {}
let concurrency = options.concurrency || Infinity
let index = 0
const results = []
const iterator = iterable[Symbol.iterator]()
const promises = []
while (concurrency-- > 0) {
const promise = wrappedMapper()
if (promise) promises.push(promise)
else break
}
return Promise.all(promises).then(() => results)
function wrappedMapper () {
const next = iterator.next()
if (next.done) return null
const i = index++
const mapped = mapper(next.value, i)
return Promise.resolve(mapped).then(resolved => {
results[i] = resolved
return wrappedMapper()
})
}
}
Promise.filter = function (iterable, filterer, options) {
options = options || {}
let concurrency = options.concurrency || Infinity
let index = 0
const results = []
const predicates = []
const iterator = iterable[Symbol.iterator]()
const promises = []
while (concurrency-- > 0) {
const promise = wrappedFilterer()
if (promise) promises.push(promise)
else break
}
return Promise.all(promises).then(() => results.filter((v, i) => predicates[i]))
function wrappedFilterer () {
const next = iterator.next()
if (next.done) return null
const i = index++
results.push(next.value)
const predicate = filterer(next.value, i)
return Promise.resolve(predicate).then(resolved => {
predicates[i] = resolved
return wrappedFilterer()
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment