记一道快手面试题的解法

1,269 阅读1分钟
// 实现一个createRequest方法(假设浏览器允许无限多的并行请求),调用形式如下图,最后实现效果如图:

// ====>
// =====>
// =======>
//     =====>
//      ======>
//        =====>
//          ====>
//            ====>

// 其中request函数的输入输出和fetch函数保持一致

以上是快手的面试题,pool表示请求池内最多可以容纳的请求个数,fn需要调用者传入,只有请求池内有完成的请求时,下一个请求才会发出去,以此类推,面试时写对了一半,现在又想了一下,写全了。 最关键的思路是else中的,内部的Promise函数调用了外部Promise函数的resolve方法,从而将结果传到外部。 在次记录一下。



function createRequest({ max, fn }) {
    let curr = 0;
    const allReq = [];

    return (...params) => {
        if (curr < max) {
            // 小于max时,立即执行该请求
            curr++;
            return fn(...params).then(res => {
                curr--;
                const next = allReq.shift();
                if (typeof next === 'function') {
                    next();
                }
                return res;
            });
        } else {
            // 大于max时,将该请求缓存到数组中,等待被其他返回的请求触发调用
           return new Promise((wrapperResolve, wrapperReject) => {
                const delayedFn = () => {
                    fn(...params).then(res => {
                        wrapperResolve(res);
                        curr--;
                        const next = allReq.shift();
                        if (typeof next === 'function') {
                            next();
                        }
                    });
                };
                allReq.push(delayedFn);
           })
        }
    }
}


const request = createRequest({
    max: 3,
    fn: n => fetch(`https://jsonplaceholder.typicode.com/todos/${n+1}`).then(res => res.json())
});


for (let i = 0; i < 100; i++) {
    request(i).then(res => {
        console.log(`${res.id} - ${res.title}`);
    }).catch(err => {
        console.log(err)
    })
}

image.png 可以看到请求请求池内最多只有3个请求,只有当请求池内小于3个请求时,下一个请求才会被发出

image.png