在循环内调用异步函数

时间:2018-08-07 16:25:51

标签: javascript asynchronous

我具有以下功能:

function ipfsRetrieve( ipfsHash ){
  return new Promise( function( resolve, reject ) {
    ipfs.catJSON( ipfsHash, (err, result) => {
        if (err){                
            reject(err);
        }
        resolve( result);           
    });
});    

}

现在,当我在如下循环中调用此函数时:

var hashArray   = [ "QmTgsbm...nqswTvS7Db",
                "QmR6Eum...uZuUckegjt",
                "QmdG1F8...znnuNJDAsd6",                    
              ]

var dataArray   = []; 
hashArry.forEach(function(hash){
    ipfsRetrieve( hash ).then(function(data){
        dataArray.push(data);
    });
});  

return dataArray

“ return dataArray”行返回一个空数组。如何更改此代码以使“ dataArray”填充有从IPFS检索的数据?

2 个答案:

答案 0 :(得分:2)

您应该使用Promise.all

构造一个承诺数组,然后使用该方法等待所有promise兑现,之后您可以按正确的顺序使用数组:

let hashArray = ["QmTgsbm...nqswTvS7Db",
  "QmR6Eum...uZuUckegjt",
  "QmdG1F8...znnuNJDAsd6",
]

// construct Array of promises
let hashes = hashArray.map(hash => ipfsRetrieve(hash));

Promise.all(hashes).then(dataArray => {
  // work with the data
  console.log(dataArray) 
});

答案 1 :(得分:1)

对于初学者来说,您需要在拒绝后返回,否则您的解决方案也会被调用。

function ipfsRetrieve( ipfsHash ){
  return new Promise( function( resolve, reject ) {
    ipfs.catJSON( ipfsHash, (err, result) => {
        if (err){                
           reject(err);
           return;
        }
        resolve( result);           
    });
});   

现在进入循环,使用map代替forEach,然后返回promise。 然后等待诺言。

let promises = hashArry.map(hash=> return new Promise(resolve,reject) { // your code here handling hash, updating theData, and then resolving })
return Promise.all(promises).then( ()=> return theData)

在您的情况下,promise由ipfsRetrieve提供,因此您可以致电

let promises = hashArry.map(ipfsRetrieve)
return Promise.all(promises)

函数的调用者将执行此操作:

ipfsRetrieve().then(data=>{ // process data here } )

如果您对异步等待很满意,请执行此操作。 (将包含功能的标记为异步)

let data = await ipfsRetrieve()