Promise并发请求,单个请求完毕后立刻处理请求

getJSON('xxxx')
.then(function(response) {
  return Promise.all(response.results.map(getJSON));
})
.then(function(series) {
  series.forEach(addDom);
});

其中getJSON() 是fetch请求,response.results是url的数组,addDom()是对数据的操作;
这段代码实现了:1.url并发请求 2.不同请求的数据顺序操作
但问题是所有请求全部加载完成后再处理数据,如何实现当前顺序的数据加载完成后就立刻对其处理而不等待其他数据


先感谢下大家的回答!
我通过其他途径拿到这样一份答案,同样利用队列,@Xeira的方法很清晰,判断任务是否完成很好理解;但下面这种方法promise用的让我有点晕,不太理解
这里用Xeira的方法改了下:

(()=>{
    Promise.allInOrder = (promises, thenForEach)=>{
        let sequence = Promise.resolve();
        
        promises.forEach(function(request){
            sequence = sequence.then(function(){
              return request.then(thenForEach);
          });
        });

    };
})();

// test
(()=>{
    let timeConsumingFunc = param=>new Promise(
            (resolve)=>{
                let timeout = Math.random() * 5000;
                console.log(`task ${param} will be resolved in ${timeout}ms`);
                setTimeout(()=>{
                    console.log(`${param} resolved`);
                    resolve(param+10);
                }, timeout);
            }
        );
    Promise
        .allInOrder(
            [timeConsumingFunc(1), timeConsumingFunc(2), timeConsumingFunc(3)],
            d=>{
                return new Promise(function(resolve) {
                  console.log(d);
                resolve();
              });
            }
        )
})();
阅读 7.5k
4 个回答

写了个例子,可以在chrome的控制台里直接执行

(()=>{
    Promise.allInOrder = (promises, thenForEach)=>{
        let callBackQueue = new Array(promises.length);
        let thenCallbackQueue = new Array(promises.length);

        let queueExecutor = ()=>{
            for(let i=0,l=callBackQueue.length;i<l;i++){
                if(callBackQueue[i] == void(0)){
                    // undefined means this task is not done yet
                    return;
                }else{
                    // execute callback
                    callBackQueue[i]();

                    // set this callback to null since it has been executed
                    callBackQueue[i] = ()=>{};
                }
            }
            // when reach here, it means all callbacks been executed
            Promise.all(thenCallbackQueue).then(ds=>{
                allPromiseResolver(ds);
            });
        };

        let allPromiseResolver = null, 
            allPromiseRejector = null;

        for(let i=0,l=promises.length;i<l;i++){

            promises[i].then(d=>{
                callBackQueue[i] = function(){
                    thenCallbackQueue[i] = new Promise((resolve, reject)=>{
                        let result = thenForEach(d);
                        resolve(result);
                    });
                };

                queueExecutor();
            });
        }

        return {
            all: callback=>{
                return new Promise((resolve, reject)=>{
                    allPromiseResolver = resolve;
                    allPromiseRejector = reject;
                }).then(ds=>{
                    callback(ds);
                });
            }
        }
    };
})();

// test
(()=>{
    let timeConsumingFunc = param=>new Promise(
            (resolve)=>{
                let timeout = Math.random() * 5000;
                console.log(`task ${param} will be resolved in ${timeout}ms`);
                setTimeout(()=>{
                    console.log(`${param} resolved`);
                    resolve(param+10);
                }, timeout);
            }
        );
    Promise
        .allInOrder(
            [timeConsumingFunc(1), timeConsumingFunc(2), timeConsumingFunc(3)],
            d=>{
                console.log(d);
                return d+20;
            }
        )
        .all((ds)=>{console.log(`all method called`);console.log(ds);})
})();
const container = document.querySelector('ul#container');
getJSON('xxxx').then(({results})=> {
  results.map((url, index) => {
    container.appendChild(document.createElement('li'));
    return getJSON(url).then(data => {
      container.querySelector(`li:nth-of-type(${index})`).innerHTML = addDom(data);
    })
  })
});

Promise.race

下面有一个场景

将每一个请求想象为一个运动员,请求数据像是运动员在赛跑,第一名奖励是可以打产品狗一巴掌,但是只能有一个人去打,那就看谁跑得快了~

all和race其实都不符合要求,all会堵到最后,而race是并发但只执行最早结束的。

其实最简单就是普通的一个循环执行所有的异步,然后给每一个异步做编号,每次异步执行完查询该编号任务是否为当前运行编号,不是就放入等待队列中。每次当前编号更新就再查询等待队列中有无对应任务。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏