Open jiefancis opened 3 years ago
var request = createRequest(3)
for(let i = 0; i < 5; i++) {
request('https://www.baidu.com').then(v => console.log(v))
}
function createRequest(capacity) {
let urls = [], runs = [], cur = 0, id = 0;
function walk(cb){
if(runs.length < capacity && urls.length) {
let item = urls.splice(0,1)[0]
cur = item.id
runs.push(item)
runs.forEach((item,index) => {
if(item.id === cur) {
item.fn().then(res => cb(res))
runs.splice(index, 1)
walk(cb)
}
})
}
}
return function(url){
let fn = () => axios({method: 'get', url})
let map = {id: id++, fn}
urls.push(map)
return new Promise((resolve, reject) => {
walk(resolve)
})
}
}
function axios({method, url}){
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest()
xhr.onreadystatechange = () => {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status >= 200 && xhr.status < 300) return resolve(xhr.response)
reject(xhr)
}
}
xhr.open(method, url)
xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8')
xhr.send()
})
}
var urls = [
'https://www.kkkk1000.com/images/getImgData/getImgDatadata.jpg',
'https://www.kkkk1000.com/images/getImgData/gray.gif',
'https://www.kkkk1000.com/images/getImgData/Particle.gif',
'https://www.kkkk1000.com/images/getImgData/arithmetic.png',
'https://www.kkkk1000.com/images/getImgData/arithmetic2.gif',
'https://www.kkkk1000.com/images/getImgData/getImgDataError.jpg',
'https://www.kkkk1000.com/images/getImgData/arithmetic.gif',
'https://user-gold-cdn.xitu.io/2018/10/29/166be40ccc434be0?w=600&h=342&f=png&s=122185'
];
function loadImg(url) {
return new Promise((resolve, reject) => {
const img = new Image()
img.onload = function () {
console.log('一张图片加载完成',url);
resolve();
}
img.onerror = reject
img.src = url
})
};
var loads = function (limit) {
var sequence = [].concat(urls);
var promises = sequence.splice(0, limit).map((url, index) => {
return loadImg(url).then(() => {
return index
})
})
return sequence.reduce((p,url,curIndex) => {
return p.then(() => Promise.race(promises)).then(index => {
// console.log("每一次是什么值", index, url)
promises[index] = loadImg(url).then(() => {
return index
})
})
}, Promise.resolve())
}
loads(3)
题意:JS实现一个带并发限制的异步调度器,保证同时运行的任务最多有两个。
题目中提到的关键信息有 并发,异步,同时运行最多两个任务。对关键词的理解如下:
1、并发意味着当任务数量超过最大并发数时,部分任务需要等待;了解js事件循环机制的读者都知道js中的任务队列是储存在事件循环产生的宏(微)任务,等待主线程执行完毕才会从任务队列中取出对应的任务执行,因此并发的实现考虑使用队列的数据结构(定义为pendings)对任务进行管理。
2、异步在js中是promise、setTimeout、async/await generator等实现异步的功能。
3、任务与任务之间花费的时间并不完全相同,为了实现任务之间时间长短的区别,可以使用setTimeout定时触发来模拟延时的功能。
4、最多两个任务需要保证当前执行的队列(runings)中最多同时存在两个任务,只有等待其中一个任务执行结束才会push新的任务。