我需要每次下载和getFiles调用单独运行,因为firebase似乎无法处理太多连接。
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.
为什么在进行所有存储桶getFiles调用之前foo / a / 0.csv开始下载?在已经拥有getFiles之后,文件下载是否已经被添加到队列的末尾了?而且foo / a有多个文件,为什么只有1个文件下载在getFiles调用之间潜入?
答案 0 :(得分:1)
嵌套结构是个问题。 当所有外部循环尚未在队列中时,没有机制来阻止内循环承诺到队列。一旦你创建了第一个Promise,它就会开始#34; work"并且将调用处理程序,因此如果您还没有添加所有Promise,并且第一个Promise达到了将Promises再次添加到队列的位置,那么您将获得所观察到的内容。
你的嵌套结构是不可能的。看看Promise.all。首先使用所有文件下载Promises构建一个不同的Array。
使用Promise.all解决所有Promise已解决的问题,然后使用内部循环将then
处理程序附加到Promise.all。
Promise.all将包含所有文件的数组,您可以通过构建另一个不同的队列来执行更多步骤。