Shanyue. tech/code/Promis…
implementation
Suppose you have a Promise for GET and an array of requests for list, and use them to request data. However, to avoid large I/OS, you need to limit the number of concurrent requests to three
function get (i) {
console.log('In ', i)
return new Promise((resolve, reject) = > {
setTimeout((a)= > {
resolve(i * 1000)
console.log('Out', i, 'Out')
}, i * 1000)})}const list = [1.2.3.4.5.6.7.8.9.10]
Copy the code
It’s easy to write a piece of loose code that implements functionality, but it’s also important to provide API design ideas. Simple implementation as follows, use count to maintain a counter of the number of concurrent
// Count the number of concurrent requests
let count = 0
function run () {
if (count < 3 && list.length) {
count+=1
get(list.shift()).then((a)= > {
count-=1
run()
})
}
}
// Limit three concurrent numbers
run()
run()
run()
Copy the code
code
Promise.map(
Iterable<any>|Promise<Iterable<any>> input,
function(any item, int index, int length) mapper,
[Object {concurrency: int=Infinity} options]
) -> Promise
Copy the code
Bluebird API is designed to be modular and easy to use. The key to the code is to maintain a queue, and when a certain number of promises are exceeded, it’s up to the queue to maintain. The following code
class Limit {
constructor (n) {
this.limit = n
this.count = 0
this.queue = []
}
enqueue (fn) {
// Fn, resolve, reject unified management
return new Promise((resolve, reject) = > {
this.queue.push({ fn, resolve, reject })
})
}
dequeue () {
if (this.count < this.limit && this.queue.length) {
// Wait until the Promise counter is less than the threshold, then queue out
const { fn, resolve, reject } = this.queue.shift()
this.run(fn).then(resolve).catch(reject)
}
}
// async/await simplifies error handling
async run (fn) {
this.count++
// Maintain a counter
const value = await fn()
this.count--
// See if there is anything in the queue
this.dequeue()
return value
}
build (fn) {
if (this.count < this.limit) {
// If the threshold is not reached, execute directly
return this.run(fn)
} else {
// If it exceeds the threshold, it will be thrown to the queue for execution when there is free time
return this.enqueue(fn)
}
}
}
Promise.map = function (list, fn, { concurrency }) {
const limit = new Limit(concurrency)
return Promise.all(list.map((. args) = > {
return limit.build((a)= >fn(... args)) })) }Copy the code
reference
Bluebird.map
Bluebird.map(list, x => {
return get(x)
}, {
concurrency: 3
})
Copy the code
The main reference is Concurrency’s implementation
featurist/promise-limit
Welcome to pay attention to my public number shanyuexixing, here records my technical growth, welcome to exchange