方案
我有一个我需要下载的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));
}
}
问题
如何动态链接承诺链?
答案
答案 0 :(得分: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);
}
}
这有效地建立了一个承诺链:
Promise
开头,其值[]
代表初始文件集:Promise.resolve([])
curPromise
的承诺然后getTransactionId
并将ID用于getFile
curFiles
(先前值)中curPromise
集的数组,并将newFile连接到其中答案 1 :(得分:0)
你可以沿着这些方向做点什么
function getAllFiles(i, results, urlArray) {
if(i == urlArray.length) return;
getTransationId().then(id => {
return new Promise((resolve, reject) => {
http.request(urlArray[i] + id, (err, response) => {
if(err){
reject();
}else{
results.push(response);
resolve();
}
});
});
}).then(() => {
getAllFiles(i + 1, results, urlArray);
})
}
答案 2 :(得分:0)
尝试使用async / await。
了解更多here
async function getFilesFromArray(urlArray) {
for(let url of urlArray){
//wrap this in a try/catch block if you want to continue with execution
//if you receive an error from one of the functions
const transactionId =await getTransactionId()
const file = await getFile(url,transactionId)
}
}
答案 3 :(得分:-1)
如果通过同步执行程序nsynjs运行逻辑,则可以简化逻辑。当某个函数计算为promise时,Nsynjs将暂停,然后将结果赋给data
属性。代码将像这样转换:
function getFilesFromArray(urlArray){
for(var i = 0; i<urlArray.length; i++) {
var trId = getTransactionId().data;
// trId is ready here
var fileContent = getFile(urlArray[i],trId).data;
// file data is ready here
console.log('fileContent=',fileContent);
};
};
nsynjs.run(getFilesFromArray,{},urls,function(){
console.log('getFilesFromArray is done');
});
getFilesFromArray可以进一步简化为:
function getFilesFromArray(urlArray){
for(var i = 0; i<urlArray.length; i++) {
var fileContent = getFile(urlArray[i],getTransactionId().data).data;
console.log('fileContent=',fileContent);
};
};