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

我试图了解为什么以下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协调许多异步操作的最佳方法是使每个异步操作返回一个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);

});

以上是 在循环中与fs.readFile一起使用Promises 的全部内容, 来源链接: utcz.com/qa/413336.html

回到顶部