串联与并联异步请求(Promise)

1,191 阅读2分钟

按照顺序,依次完成异步请求

需要将多个异步请求的结果按照顺序输出。

给定一个数组list,数组中的每一项包含id、name和delay属性。需要按照idList中的顺序,查找相应id对应的name和delay,在延迟delay秒后,输出name。

const list = [
{id: 'id_a', name: 'foo', delay: 2},
{id: 'id_b', name: 'bar', delay: 4},
{id: 'id_c', name: 'baz', delay: 1},
{id: 'id_x', name: 'str_x', delay: 3}
];
const idList =['id_b', 'id_x', 'id_a', 'id_c'];

这可以看作是每次只允许一个并发请求的情况。

function inOrder(list, idList){
    // 通过一个循环将promise串起来
    const recursion = (id, prev) => {
        let {name, delay} = list.find(v => v.id === id);
        // 由于需要使用到setTimeout,用Promise包一层
        return new Promise((resolve, reject) => {
            setTimeout(()=>{
                console.log(prev ? prev + '-'+ name: name);
                resolve(prev ? prev + '-'+ name: name);
            }, delay * 1000)
        }).then((val) => {
            // 判断当前数组是否遍历完成了,没有完成传递数组首位参数调用循环
            if(idList.length){
                return recursion(idList.shift(), val);
            }
            // 数组遍历完成后,直接传递最终结果
            return val;
        })
    }
    // 可以看作是并发请求数为1的情况,直接调用循环
    return recursion(idList.shift(), '');
}

inOrder(list, idList).then((val) => {
    console.log(val);
})

在最短的时间内,完成所有异步请求?如果有最大并发数限制呢?

假设加法需要通过异步请求完成,如何在最快的时间内计算出一个数组中数的总和?

在不考虑并发数限制的情况下,发起尽可能多的异步请求,将每次异步请求后的结果放回数组中,如果数组中的数会大于2个,就接着再发起请求。直到数组中只剩下一个数时,这个数就是计算的总和了。最后用一个Promise.all等待并发请求数组中的请求都执行完。

如果有并发数的限制,就是在while(idList.length >= 2)中再添加一个限制的判断,如while(idList.length >= 2 && limit--)

function request(num1, num2){
    return new Promise((res, rej) => {
        setTimeout(()=>{
            res(num1 + num2);
        }, 1000)
    })
}

const idList =[1,2,3,4,5,6,7];

function calc(){
    const recursion = (num1, num2) => {
        // 调用加法请求
        return request(num1, num2).then((val) => {
            // 将请求返回的结果放回数组中,还需要跟数组中的其他数做加法
            idList.push(val);
        }).then(() => {
            // 如果当前数组中的数大于2个时,再次调用递归函数处理数组中的最后两个数
            if(idList.length >= 2){
                return recursion(idList.pop(), idList.pop());
            }else{
                // 否则的话返回最后的结果
                return idList;
            }
        })
    }
    // 用来存储所有的异步请求
    let asyncList = [];
    // 当数组中的数大于2个时,调用递归函数处理目前数组中的最后两个数,并将这两个数移出数组
    while(idList.length >= 2){
        asyncList.push(recursion(idList.pop(), idList.pop()));
    }

    // 利用Promise.all等待异步请求数组中的请求都执行完
    return Promise.all(asyncList);
}

calc().then((val) => console.log(val))