ES6 Dyanmic Promise链接来自阵列

Sim*_*mon 1 javascript node.js promise ecmascript-6 es6-promise

脚本

我有一个需要下载的URL数组,但每个URL也必须提供一个必须从服务器请求的唯一事务ID,并且只在请求成功时递增.

问题

当我循环遍历数组时,我需要等待事务ID的请求和文件的请求在开始循环的下一次迭代之前完成,但文件的数量不固定,因此需要动态构建链承诺.

伪代码

下面是一些伪代码,getFiles()是问题,因为所有请求都获得相同的事务ID,因为它们不等待先前的请求完成.

function getTransationId(){
    return new Promise((resolve,reject)=> {
        let id = getNextTransactionId();
        if(id!=error){
            resolve(id);
        }else{
            reject(error);
        }
    })
}

function getFile(url, transactionId){
    return new Promise((resolve,reject)=>{
        http.request(url+transactionId, function(err,response){
            if(err){
                reject(err);
            }else{
                resolve(response);
            }
        });
    });
}

function getFilesFromArray(urlArray){
    for(let url of urlArray){
        getTransactionId().then(resolve=>getFile(url,resolve),reject=>console.error(reject));
    }
}
Run Code Online (Sandbox Code Playgroud)

如何动态链接链承诺?

回答

这是Ovidiu答案的JSFiddle

Ovi*_*lha 6

一种功能性方法是用于reduce迭代并返回从每个子承诺链接的最终承诺.它还有助于构建结果,例如在数组中:

function getFilesFromArray(urlArray){
    const filesPromise = urlArray.reduce((curPromise, url) => {
        return curPromise
           .then(curFiles => {
                return getTransactionId()
                    .then(id => getFile(url, id))
                    .then(newFile => [...curFiles, newFile]);
           });
    }, Promise.resolve([]));

    filesPromise.then(files => {
         console.log(files);
    }
}
Run Code Online (Sandbox Code Playgroud)

这有效地构建了一个承诺链:

  • 以静态开头,其Promise[]表示初始文件集:Promise.resolve([])
  • 在每次迭代中,返回一个等待curPromise链中的promise 然后
  • 执行getTransactionId并使用id来getFile
  • 一旦文件被检索,它将返回一个包含(之前的值)中的curFiles集合的数组,并将curPromisenewFile连接到其中
  • 最终结果将是收集所有文件的单一承诺