JavaScript请实现,最多允许同时发三个ajax请求,有100个请求要发送。

原题

版本一:
 

const pipRequest = (idsarr, callback) => {

    const start = Date.now();

    const len = idsarr.length;
    const result = []; // 结果集
    const ajaxMax = 3; // 最多允许同时执行的ajax次数
    let ajaxNum = 0; // 当前有多少ajax正在执行

    const ajax = (id) => new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(`${id}的结果`);
        }, 500);
    })

    const main = (ids) => {
        console.log(`时间:${Date.now() - start}`);
        while (ajaxNum <= ajaxMax && ids.length > 0) { // 只要有位置就发请求
            ajaxNum++;
            const now = ids.shift() // 发了一个请求
            ajax(now).then(res => {
                result.push(res);
                main(ids);
            }).catch((_) => {
                ids.push(now); // 失败的请求重新加入队列
            }).finally(() => {
                ajaxNum--;
                (
                    result.length === len
                    && typeof callback === 'function'
                    && callback(result)
                );
            })

        }
    }
    main(idsarr);
}

pipRequest([...Array(100).keys()], function (res) {
    console.log(res);
})

版本二:
这个版本比较好理解,但是实现私有属性的#方法兼容性很差。


 

const ajax = (id) => new Promise((resolve, reject) => setTimeout(() => {
    resolve(`${id}结果`);
}, 500))
class Request {
    // 初始化数据
    constructor(arr = [], callback) {
        this.arr = arr;
        this.callback = this.#checkCallBackLegal(callback) && callback;
    }

    #result = [];
    #curIndex = 0;
    #maxNum = 3;
    #pool = new Set();

    // 启动函数,从arr的第0项开始启动
    async start() {
        await this.#addPool();
    }

    // 加入池子,如果池中满了或者超出则不放置
    #addPool = ()=>{
        if (this.#pool.size < this.#maxNum && this.arr.length > this.#curIndex) {
            const id = this.#send();
            this.#pool.add(id);
            this.#curIndex++;
            this.#addPool();
        }
    }

    // 移出池子
    #removePool = (id)=>{
        this.#pool.delete(id)
    }

    // 返回ajax,单个请求
    #send = ()=>{
        const id = this.#curIndex;
        ajax(this.arr[id]).then((res) => {
            this.#log(res);
            this.#result.push(res);
        }).then(res => {
            this.#removePool(id);
            this.#addPool();
            this.#doCallBack()
        });
        return id;
    }

    #log = (res)=>{
        console.log(`${res} has been resolved`);
    }

    #checkCallBackLegal = (callback)=>{
        return (callback && typeof callback === 'function');
    }

    #doCallBack = ()=>{
        if (this.arr.length === this.#result.length) {
            this.callback(this.#result);
        }
    }
}

const arr = [...Array(100).keys()];
new Request(arr, (res) => {
    console.log(res);
}).start();

版本三:
这个版本的私有成员兼容性比较好,但是这TM也太难看了,突然想说java真香,JavaScript就是个垃圾。
 

// 函数闭包化
const closure = (func) => {
    return (func)();
}
// ajax
const ajax = (id) => new Promise((resolve, reject) => setTimeout(() => {
    resolve(`${id}结果`);
}, 500))


var Request =() => {
    // 实现私有属性
    const result = Symbol();
    const curIndex = Symbol();
    const maxNum = Symbol();
    const pool = Symbol();
    const addPool = Symbol();
    const removePool = Symbol();
    const send = Symbol();
    const log = Symbol();
    const checkCallBackLegal = Symbol();
    const doCallBack = Symbol();

    class Request {
        constructor(arr = [], callback) {
            // 初始化数据
            this.arr = arr;
            this.callback = this[checkCallBackLegal](callback) && callback;
            // 初始化私有属性
            this[result] = [];
            this[curIndex] = 0;
            this[maxNum] = 3;
            this[pool] = new Set();
        }

        // 启动函数,从arr的第0项开始启动
        async start() {
            await this[addPool]();
        }

        // 加入池子,如果池中满了或者超出则不放置
        [addPool]() {
            if (this[pool].size < this[maxNum] && this.arr.length > this[curIndex]) {
                this[send]();
                this[pool].add(this[curIndex]);
                this[curIndex]++;
                this[addPool]();
            }
        }

        // 移出池子
        [removePool](id) {
            this[pool].delete(id)
        }

        // 返回ajax,单个请求
        [send]() {
            const id = this[curIndex];
            ajax(this.arr[id]).then((res) => {
                this[log](res);
                this[result].push(res);
            }).then((_) => {
                this[removePool](id);
                this[addPool]();
                this[doCallBack]();
            });
        }

        // 打印日志
        [log](res) {
            console.log(`${res} has been resolved`);
        }

        // 检查回调函数是否合法
        [checkCallBackLegal](callback) {
            return (callback && typeof callback === 'function');
        }

        // 执行回调函数
        [doCallBack]() {
            // 执行回调函数的时机判断,
            if (this.arr.length === this[result].length) {
                this.callback(this[result]);
            }
        }
    }
    return Request;
}

var RequestClosure = closure(Request);

const arr = [...Array(100).keys()];
new RequestClosure(arr, (res) => {
    console.log(res);
}).start();
const start = Date.now();

const ajax = () => new Promise(resolve => {
    setTimeout(() => {
        resolve(true);
    }, 500);
});

function multiRequest(urls = [], maxNum) {
    // 请求总数量
    const len = urls.length;
    // 根据请求数量创建一个数组来保存请求的结果
    const result = new Array(len).fill(false);
    // 当前完成的数量
    let count = 0;

    return new Promise(resolve => {
        while (count < maxNum) {
            next();
        }

        const save = (res, current) => {
            result[current] = res;
            console.log(res,Date.now() - start);
            if (current < len) {
                next();
            }
        }


        function next() {
            let current = count++;
            if (current >= len) {
                result.every(Boolean) && resolve(result);
                return;
            }
            ajax(urls[current])
                .then((res) => save(res, current))
                .catch((res) => save(res, current))
        }
    });
}


multiRequest([...Array(100).keys()],3)

 

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用 JavaScript 中的 Promise 和 async/await 来实现这个功能。具体步骤如下: 1. 定义一个数组来存储所有的请求 Promise 对象。 2. 使用 for 循环遍历所有需要异步请求的接口,将每个接口的请求封装成 Promise 对象,并将其 push 到数组中。 3. 定义一个并请求数量的变量,初始化为 0。 4. 使用 while 循环不断遍历数组中的 Promise 对象,直到所有 Promise 都被处理完毕。 5. 在 while 循环中,先判断并请求数量是否小于 3,如果是,则将并请求数量加 1,然后取出数组中的一个 Promise 对象进行请求,并使用 await 等待请求结果。 6. 在请求结束后,将并请求数量减 1,然后继续执行 while 循环,直到所有 Promise 都被处理完毕。 下面是实现代码的示例: ```javascript async function concurrentRequest(urls) { const promises = urls.map(url => { return new Promise(resolve => { // 发送异步请求 const xhr = new XMLHttpRequest(); xhr.open('GET', url); xhr.onload = function() { resolve(xhr.responseText); }; xhr.send(); }); }); let concurrency = 0; let index = 0; while (index < promises.length) { if (concurrency < 3) { concurrency++; await promises[index]; concurrency--; index++; } else { await new Promise(resolve => { setTimeout(resolve, 100); }); } } } ``` 使用方法: ```javascript const urls = ['url1', 'url2', 'url3', ...]; concurrentRequest(urls); ``` 其中,`urls` 是需要异步请求的接口列表。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值