2017-06-02 59 views
0

我需要每个下载和getFiles调用分开运行,因为firebase似乎无法处理太多的连接。Node.JS:为什么嵌套promise应用程序似乎无序运行?

const bucket = storage.bucket(bucketName); // firebase storage bucket 
var queue = Promise.resolve(); 

websiteNames.reduce(function(promise, websiteName) { 
    return promise 
    .then(() => { 
     mkdirp(websiteName) 
    }) 
    .then(() => { 
     console.log("now getting files: " + dirPath); 
     return bucket.getFiles({prefix: dirPath}) 
    }) 
    .then(data => { 
     console.log("got files"); 
     var files = data[0]; 
     files.forEach(function (file) { 
      var storePath = tmpDir + "/" + file.name; 
      queue = queue 
      .then(() => { 
       console.log("now downloading: " + file.name); 
       return file.download({destination: storePath}); 
      }) 
      .then(() => { 
       console.log(`downloaded to ${storePath}.`); 
       return readFile(storePath, 'utf8'); 
      }) 
      .then(buffer => { 
       console.log("readed file: " + storePath + " of buf size " + buffer.length); 
      }); 
     }); 
    }); 
}, queue); 

我预计big then block会将下载动作添加到已经拥有所有getFiles动作的队列中。所以我希望它在开始下载文件之前完成所有的getFiles调用。但是,控制台日志是这样的:

now getting files: foo/a 
got files 
now downloading: foo/a/0.csv 
now getting files: foo/b 
got files 
now getting files: foo/c 
got files 
downloaded to /tmp/foo/a/0.csv. 

为什么富/ A/0.csv开始下载所有的桶的GetFiles调用才制成?在已经有getFiles thens之后,是否不应该将文件下载的thens文件添加到队列末尾?而且,foo/a有多个文件,为什么只有一个文件下载在getFiles调用之间?

+1

你是在误解诺言。您遍历您的网站名称并将处理程序附加到您的承诺。无论先发生什么,它们将被异步执行。 虽然有Promise队列的js插件。 – Strernd

回答

1

嵌套结构是问题。 没有任何机制来阻止内部循环向队列做出承诺,当所有外部循环都不在队列中时。只要你创建第一个Promise,它就会开始“工作”,处理程序将被调用,所以如果你没有添加所有的Promise,并且第一个Promise达到了将Promises添加到队列中的点,你会得到你观察到的。

你的嵌套结构是什么使它不可能。看看Promise.all。首先用所有文件下载Promise构建一个独立的数组。 当Promise.all解决了所有的承诺后,询问Array,然后将then处理程序附加到带有内部循环的Promise.all中。

Promise.all将包含所有文件的数组,您可以通过构建另一个不同的队列来执行更多步骤。

+0

我无法理解“但是由于您将处理程序附加到多个承诺中” - 哪些处理程序和我在哪里执行?发生这种情况是因为第一个websiteName mkdirp和getFiles在最外层reduce循环完成运行之前完成了吗?从而导致竞争状况? 队列示例如何与forEach循环一起工作(文件列表下载后需要单独下载文件)? – pete

+0

@pete 我忽略了代码中的某些内容,但承诺队列仍然适用。 请考虑以下情况。 您首先将所有处理程序附加到A.然后立即开始工作,并行地添加B,C 现在,处理程序A到达files.foreach块并将更多事件添加到队列中。 A1,A2,A3 然后你添加D,E,等等。 问题是没有什么可以阻止内部循环向您的队列添加承诺。 – Strernd

+0

@pete我知道这一切都错了,但相应地更新了我的答案。试试看,如果这没有帮助,再次提及我,我们会弄清楚。 – Strernd

相关问题