Javascript ES6阵列的动态承诺链
场景 我有一个需要下载的URL数组,但是每个URL还必须提供一个唯一的事务ID,该ID必须从服务器请求,并且只有在请求成功时才会递增 问题 当我在数组中循环时,我需要等待事务ID请求和文件请求完成,然后再开始循环的下一次迭代,但文件的数量不是固定的,因此需要动态构建承诺链 伪代码 下面是一些伪代码,getFiles()是问题所在,因为所有请求都获得相同的事务Id,因为它们不等待前一个请求完成Javascript ES6阵列的动态承诺链,javascript,node.js,ecmascript-6,promise,es6-promise,Javascript,Node.js,Ecmascript 6,Promise,Es6 Promise,场景 我有一个需要下载的URL数组,但是每个URL还必须提供一个唯一的事务ID,该ID必须从服务器请求,并且只有在请求成功时才会递增 问题 当我在数组中循环时,我需要等待事务ID请求和文件请求完成,然后再开始循环的下一次迭代,但文件的数量不是固定的,因此需要动态构建承诺链 伪代码 下面是一些伪代码,getFiles()是问题所在,因为所有请求都获得相同的事务Id,因为它们不等待前一个请求完成 function getTransationId(){ return new Promise((
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));
}
}
问题
如何动态地将承诺链接在一起
回答
下面是一个答案你可以按照这些思路做一些事情
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);
})
}
你可以按照这些思路做一些事情
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);
})
}
尝试使用异步/等待
阅读更多
尝试使用异步/等待
阅读更多
函数方法是使用
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.resolve([])
- 在每次迭代中,返回一个承诺,该承诺在链中等待
,然后curPromise
- 执行
并使用该id来getTransactionId
getFile
- 一旦检索到文件,它将返回一个数组,其中包含
中设置的curPromise
(以前的值),并将新文件连接到其中curFiles
- 最终的结果将是收集所有文件的单一承诺
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.resolve([])
- 在每次迭代中,返回一个承诺,该承诺在链中等待
,然后curPromise
- 执行
并使用该id来getTransactionId
getFile
- 一旦检索到文件,它将返回一个数组,其中包含
中设置的curPromise
(以前的值),并将新文件连接到其中curFiles
- 最终的结果将是收集所有文件的单一承诺
data
property。代码将按如下方式转换:
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(urlArray){
对于(var i=0;i,如果通过同步执行器运行它,则可以简化逻辑。当某个函数的计算结果为promise时,Nsynjs将暂停,然后将结果分配给
数据
属性。代码将按如下方式转换:
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(urlArray){
对于(var i=0;i选中此项:如果
getNextTransactionId
返回id
,为什么需要将其包装在承诺中?然后将您的示例与未定义的错误进行比较。如果不知道getNextTransactionId
返回的是什么,则很难判断是什么导致了问题。getTransactionId()
是对服务器的调用,因此我们需要在继续之前等待响应,否则Id将是未定义的
。就错误而言,我过度简化了过程以说明问题,因此调用是伪代码。请检查:如果getNextTransactionId
返回Id
,为什么需要将其包装在Promise中?然后将您的示例与未定义的错误进行比较。如果不知道getNextTransactionId
返回的是什么,则很难判断是什么导致了问题。getTransactionId()
是对服务器的调用,因此我们需要在继续之前等待响应,否则Id将是未定义的
。就错误而言,我过度简化了过程以说明问题,因此调用是伪代码。ES6又称ES2015不包括async/wait。此功能仅在ES2017中正式就绪。nodejs关闭ICIALY从7.6ES6版本(也称ES2015)支持此功能,但不包括async/await。此功能仅在ES2017中正式提供。nodejs从7.6版本正式支持此功能。非常好的答案,[…a,b]
对我来说是新语法,非常漂亮。谢谢。非常好的答案,[…a,b]
对我来说是新的语法,它很漂亮。谢谢。