Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/41.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/387.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript ES6阵列的动态承诺链_Javascript_Node.js_Ecmascript 6_Promise_Es6 Promise - Fatal编程技术网

Javascript ES6阵列的动态承诺链

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((

场景

我有一个需要下载的URL数组,但是每个URL还必须提供一个唯一的事务ID,该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));
    }
}
问题

如何动态地将承诺链接在一起

回答


下面是一个答案

你可以按照这些思路做一些事情

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
    ,然后

  • 执行
    getTransactionId
    并使用该id来
    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
    ,然后

  • 执行
    getTransactionId
    并使用该id来
    getFile
  • 一旦检索到文件,它将返回一个数组,其中包含
    curPromise
    中设置的
    curFiles
    (以前的值),并将新文件连接到其中
  • 最终的结果将是收集所有文件的单一承诺

如果通过同步执行器运行逻辑,则可以简化逻辑。当某个函数的计算结果为promise时,Nsynjs将暂停,然后将结果分配给
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]
对我来说是新的语法,它很漂亮。谢谢。