当前位置: 首页 > 面试题库 >

在循环中与fs.readFile一起使用Promises

高飞翮
2023-03-14
问题内容

我试图了解为什么以下promise设置不起作用。

(注意:我已经使用async.map解决了这个问题。但是,我想了解为什么我的以下尝试不起作用。)

正确的行为应该是:bFunc应该运行所需的时间,以便fs读取所有图像文件(下面的bFunc运行两次),然后cFunc控制台打印“结束”。

谢谢!

尝试1:它在cFunc()处运行和停止。

var fs = require('fs');

bFunc(0)
.then(function(){ cFunc() }) //cFunc() doesn't run

function bFunc(i){
    return new Promise(function(resolve,reject){

        var imgPath = __dirname + "/image1" + i + ".png";

        fs.readFile(imgPath, function(err, imagebuffer){

            if (err) throw err;
            console.log(i)

            if (i<1) {
                i++;
                return bFunc(i);
            } else {
                resolve();
            };

        });

    })
}

function cFunc(){
    console.log("End");
}

尝试2:在这种情况下,我使用了for循环,但执行顺序混乱。控制台打印:结束,bFunc完成,bFunc完成

var fs = require('fs');

bFunc()
        .then(function(){ cFunc() })

function bFunc(){
    return new Promise(function(resolve,reject){

        function read(filepath) {
            fs.readFile(filepath, function(err, imagebuffer){
                if (err) throw err;
                console.log("bFunc done")
            });
        }

        for (var i=0; i<2; i++){
            var imgPath = __dirname + "/image1" + i + ".png";
            read(imgPath);
        };

        resolve()
    });
}


function cFunc(){
    console.log("End");
}

我在这里先向您的帮助表示感谢!


问题答案:

因此,只要您有多个异步操作以某种方式进行协调,我都会立即承诺。并且,使用promise协调许多异步操作的最佳html" target="_blank">方法是使每个异步操作返回一个promise。您显示的最低级别的异步操作是fs.readFile()。由于我使用了Bluebird
Promise库,因此它具有用于“保证”整个模块有价值的异步功能的功能。

var Promise = require('bluebird');
var fs = Promise.promisifyAll(require('fs'));

这将在fs带有“异步”后缀的对象上创建新的并行方法,该后缀返回承诺而不是使用直接回调。因此,将有一个fs.readFileAsync()返回承诺的机会。您可以在此处阅读有关Bluebird传播的更多信息。

因此,现在您可以创建一个函数,该函数可以非常简单地获取图像并返回一个promise,其值是图像中的数据:

 function getImage(index) {
     var imgPath = __dirname + "/image1" + index + ".png";
     return fs.readFileAsync(imgPath);
 }

然后,在您的代码中,您似乎想bFunc()成为一个函数,可以读取其中的三个图像并cFunc()在完成后调用。您可以这样做:

var Promise = require('bluebird');
var fs = Promise.promisifyAll(require('fs'));

 function getImage(index) {
     var imgPath = __dirname + "/image1" + index + ".png";
     return fs.readFileAsync(imgPath);
 }

 function getAllImages() {
    var promises = [];
    // load all images in parallel
    for (var i = 0; i <= 2; i++) {
        promises.push(getImage(i));
    }
    // return promise that is resolved when all images are done loading
    return Promise.all(promises);
 }

 getAllImages().then(function(imageArray) {
    // you have an array of image data in imageArray
 }, function(err) {
    // an error occurred
 });

如果您不想使用Bluebird,则可以手动创建一个Promise版本,fs.readFile()如下所示:

// make promise version of fs.readFile()
fs.readFileAsync = function(filename) {
    return new Promise(function(resolve, reject) {
        fs.readFile(filename, function(err, data){
            if (err) 
                reject(err); 
            else 
                resolve(data);
        });
    });
};

或者,在现代版本的node.js中,您可以util.promisify()用来制作遵循node.js异步调用约定的函数的承诺版本:

const util = require('util');
fs.readFileAsync = util.promisify(fs.readFile);

不过,您会很快发现,一旦开始使用Promise,您就想将其用于所有异步操作,这样您就可以“许诺”很多事情,并拥有一个可以满足您需求的库或至少一个泛型函数节省大量时间。

在更高版本的node.js(版本10.0+)中,您可以使用fs支持promise 的库的内置版本:

const fsp = require('fs').promises;

fsp.readFile("someFile").then(data => {
    console.log(data);
});


 类似资料:
  • 我希望我可以序列化(稍后反序列化)为如下所示:(但对JSON不太确定) 我怎么能那样做?

  • 问题内容: 这有效: 但是,这不是: 在第二个示例中,数组未添加到自身。 问题答案: 是的,不是 您所做的可能也是有效的代码,但是现在您正在做 它适用于数字类型(我假设您有)。没有数组索引的简化示例: 样品: 输出: -5 -5 5 5 为了清晰起见,从评论中复制: 您基本上是在说。在这种情况下,仅需指示它是一个正整数即可。这是有效的代码,但这不是您想要的。

  • 问题内容: 根据我的理解,如果没有其他“指向”该对象的内容,则Java中的垃圾回收会清除某些对象。 我的问题是,如果我们有这样的事情怎么办: 和应该被垃圾回收,但是它们都被其他对象引用。 Java垃圾回收如何处理呢?(或者仅仅是内存消耗?) 问题答案: 如果无法通过从垃圾回收根开始的链访问对象,Java的GC会将其视为“垃圾”,因此将收集这些对象。即使对象可能指向彼此以形成一个循环,但如果将它们与

  • 问题内容: 我一直在慢慢学习Tkinter和面向对象的编程,但是我已经将自己编程与此有关。请原谅我对这一观点缺乏批判性思考,但是我已经问过我认识的每个人,谁比我更了解python,所以我们不能在这里找到可行的解决方案。 我有一个正在运行的gui应用程序,它允许用户输入股票代码,为每个代码创建新标签,然后定期更新每个标签。(有点像一个非常基本的电子商务应用程序之类的东西)。我发现没有gui做到这一点

  • 我用tomee创建了一个项目,我想使用stomp协议在我的web应用程序和使用ActiveMQ作为MOM的客户端之间交换消息,但当我运行tomee时,会出现以下异常: 线程“ActiveMQ传输服务器线程处理程序中出现异常:stomp://0.0.0.0:61222“java.lang.NoClassDefFoundError:com/thoughtworks/xstream/io/Hierarc

  • 我有: 它记录了: 我不明白为什么会这样。