【问题标题】:Using Bluebird Promises in Node.JS在 Node.JS 中使用 Bluebird Promise
【发布时间】:2015-10-10 00:40:52
【问题描述】:

在我的应用程序中,我试图读取一个文件,然后将该文件的内容写入另一个文件。

我已经使用 bluebird promises 来做到这一点。我需要帮助来确认我对使用 Promise 的理解在我的实现中是正确的。

我的问题是,

  1. 在我的示例中,我首先读取文件,然后在文件读取文件后,将内容写入下一个“.then”块中的另一个文件。将内容写入文件后,我需要记录一条消息。我已将其包含在第二个“.then”块中。我需要知道我对承诺的理解是否正确。第二个 '.then' 块会作为 writefile 语句的回调函数吗?

  2. 我需要编写更有意义的日志消息。如果在读取文件和写入文件时发生错误,则会出现不同的错误消息。如何使用 catch 块做到这一点?

提前致谢!

代码示例如下。

var Promise = require("bluebird");
var fs = Promise.promisifyAll(require("fs"));
var logger = require("./logger.js")
var projectJSON = require("../project.json");

var harPath = projectJSON.project.harfile.location;
var harFileNames = projectJSON.project.transactions.transactionsName;
var harFilePath;
var harFiles = {};
var writeFilePath = "../temp/"


harFileNames.forEach(function(harFileName){
    harFilePath = harPath + "/" + harFileName + ".har";

    fs.readFileAsync(harFilePath, "utf-8")
        .then(function(data){
            fs.writeFile(writeFilePath + harFileName + ".json", data);
            test = data;

        })
        .then(function(){
            console.log("data written successfully: ");

        })
        .catch(function(err){
            logger.error("error", "Error reading har files from location!");

        });

});

【问题讨论】:

    标签: javascript node.js bluebird


    【解决方案1】:

    如果您想分别捕获每个错误,那么您可以在每个操作之后立即放置一个错误处理程序,这样您就可以直接捕获该特定错误。

    然后,为了传播错误,您可以重新抛出错误值。

    然后,你想切换到fs.writeFileAsync(),所以一切都是异步的并且正在使用 Promise。

    然后,你需要从fs.writeFileAsync()返回promise。

    var Promise = require("bluebird");
    var fs = Promise.promisifyAll(require("fs"));
    var logger = require("./logger.js")
    var projectJSON = require("../project.json");
    
    var harPath = projectJSON.project.harfile.location;
    var harFileNames = projectJSON.project.transactions.transactionsName;
    var harFilePath;
    var harFiles = {};
    var writeFilePath = "../temp/"
    
    
    harFileNames.forEach(function(harFileName){
        harFilePath = harPath + "/" + harFileName + ".har";
    
        fs.readFileAsync(harFilePath, "utf-8")
            .then(function(data){
                harFiles[JSON.parse(data).log.pages[0].id] = JSON.parse(data);
                return data;
            }).catch(err) {
                logger.error("error", "Error reading har files from location!");
                throw err;      // propagate error
            }).then(function(data){
                return fs.writeFile(writeFilePath + harFileName + ".json", data).catch(function(err) {
                    logger.error("error", "Error writing to harFile!");
                    throw err;   // propagate error
                });
            }).then(function(){
                console.log("data written successfully: ");
            }).catch(function(err){
                // either one of the errors
            });
    
    });
    

    请记住,当您有一个 .catch() 处理程序时,错误被视为“已处理”并且生成的承诺将被履行,而不是被拒绝。因此,如果您想在特定位置捕获错误(这样您就可以确切地知道它来自哪里),但您希望得到的 Promise 仍然被拒绝,那么您可以返回被拒绝的 Promise 或重新抛出相同的错误。


    根据您关于如何返回harFiles 的其他问题,您将需要一个环绕的承诺,当一切都完成后,该承诺将通过harFiles 得到解决。 Bluebird 的Promise.map() 对此很有用,因为它既会为您进行迭代,又会返回一个主承诺。下面是这部分代码的样子:

    function someFunc() {
    
        var harPath = projectJSON.project.harfile.location;
        var harFileNames = projectJSON.project.transactions.transactionsName;
        var harFilePath;
        var harFiles = {};
        var writeFilePath = "../temp/"
    
        return Promise.map(harFileNames, function(harFileName) {
            harFilePath = harPath + "/" + harFileName + ".har";
    
            return fs.readFileAsync(harFilePath, "utf-8")
                .then(function(data){
                    harFiles[JSON.parse(data).log.pages[0].id] = JSON.parse(data);
                    return data;
                }, function(err) {
                    logger.error("error", "Error reading har files from location!");
                    throw err;      // propagate error
                }).then(function(data){
                    return fs.writeFile(writeFilePath + harFileName + ".json", data).catch(function(err) {
                        logger.error("error", "Error writing to harFile!");
                        throw err;   // propagate error
                    });
                }).then(function(){
                    console.log("data written successfully: ");
                }).catch(function(err){
                    // either one of the errors
                });
    
        }).then(function() {
            // all results are in harFiles array here
            return harFiles;
        });
    }
    
    someFunc().then(function(hFiles) {
        // hFiles should be your files object
    });
    

    【讨论】:

    • 感谢您的回答。在您的示例中,您在每个 catch 块中都抛出了错误,以使结果承诺被拒绝,是吗?还有一个问题,这段代码在函数内部。一旦它读取所有文件并将它们写入新位置,如示例中所述,我想返回 harFiles 对象数组。当我在 for each 循环之后包含我的返回行时,由于异步行为,它返回“未定义”。我该怎么做?
    • @Hamza - 是的,throw err 行是为了确保生成的承诺保持被拒绝,因此不会尝试此链中的进一步操作,并且被拒绝的原因一直到最后.我在关于返回harFiles 的答案中添加了另一部分。
    • 非常感谢您的帮助。
    • 我尝试了您的第二个解决方案,但它对我不起作用。为了测试我的 harFiles 对象中的值,我添加了一个循环来输出“then”部分中的值,但是没有用。
    • @Hamza - 你在调用包含函数时使用了.then()。请参阅我在答案中添加到第二个代码示例的额外说明。
    猜你喜欢
    • 2014-05-10
    • 1970-01-01
    • 2015-03-04
    • 1970-01-01
    • 2018-05-06
    • 2016-12-10
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    相关资源
    最近更新 更多