javascript - Node.JS:为什么嵌套的 Promise then 似乎乱序了?

标签 javascript node.js firebase promise firebase-storage

我需要每个 download 和 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);

我预计大的 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.

为什么 foo/a/0.csv 在所有存储桶 getFiles 调用完成之前就开始下载?在已经有 getFiles thens 之后,文件下载 thens 不应该被添加到队列的末尾吗?此外 foo/a 有多个文件,那么为什么在 getFiles 调用之间只下载了 1 个文件?

最佳答案

嵌套结构是问题所在。 当所有外部循环尚未进入队列时,没有机制可以阻止内部循环向队列 promise 。一旦你创建了第一个 Promise,它就会开始“工作”,并且处理程序将被调用,因此,如果你没有完成添加所有 Promise,并且第一个 Promise 达到了再次将 Promise 添加到队列的程度,你就会得到你所观察到的结果。

你的嵌套结构使得它变得不可能。看看Promise.all 。首先使用所有文件下载 promise 构建一个不同的数组。 当所有 Promise.all 都已解决时询问数组,然后使用内部循环将 then 处理程序附加到 Promise.all。

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

关于javascript - Node.JS:为什么嵌套的 Promise then 似乎乱序了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44323402/

相关文章:

javascript - Firefox 中的 Accordion 盒故障

javascript - Php 运行 nodejs javascript grunt 任务

javascript - 在 if 语句中使用 child_process.exec 的返回值?

firebase - 方法 'setData' 没有为类型 'documentreference' 定义

swift - 从 firebase 下载图像链接时得到零

javascript - Firebase 函数 : sync with Algolia doesn't work

javascript - 如何使用 JS 中的转换自动对齐 SVG "g"元素?

javascript - 通过 jQuery 切换使用 SVG 图标

node.js - 无法访问 Mongoose 响应的对象属性

javascript - Node 没有从 Firebase 数据库中删除?