这是将readFileSync包装在承诺中的正确方法吗?

Is this the correct way to wrap readFileSync in a Promise

本文关键字:方法 承诺 readFileSync 包装      更新时间:2023-09-26

下面代码的原因是摆脱callback hell/pyramid of doom。不过我还不完全明白i/o blocking

'use strict';
var fs = require('fs');
var co = require('co');
co(function* () {
    var fileName = 'readme.txt';
    var str =
        yield new Promise(function (resolve, reject) {
            var result;
            try {
                result = fs.readFileSync(fileName, 'utf8');
            } catch (err) {
                reject(err);
            }
            resolve(result);
        });
    console.log('result readFileSync: ' + str);
});

老实说,我所期待的只是一个yesno答案。完全希望如果没有,有人可以提供一些细节,因为我正在尝试正确学习JavaScript同步/异步以及如何利用Promises的力量。

简答

有用的答案

如果要包装文件读取操作,请尝试尽可能多地使用 Node 函数的异步版本。与单独使用readFileSync相比,使用带有 promise 的 readFileSync 没有任何优势,因为readFileSync会阻止该过程,直到它完成读取,而readFile不会。

因此,更好的解决方案是这样的:

'use strict';
var fs = require('fs');
var readFilePromise = function(file) {
  return new Promise(function(ok, notOk) {
    fs.readFile(file, function(err, data) {
        if (err) {
          notOk(err)
        } else {
          ok(data)
        }
    })
  })
}
readFilePromise('/etc/passwd').then(function(data) {
  // do something with the data...
})

正确的方法是使用 Node 的原生 util 库和 promisfy fs.readFile

const path = require('path');
const fs = require('fs');
const INDEX = path.join(__dirname, 'app', 'index.html');
const readFile = require('util').promisify(fs.readFile);
readFile(INDEX)
  .then(e => console.log(e.toString()))
  .catch(e => console.log('FOOBAR ' + e));

结果:

one@dolphin:~/github/resume $ node toolchain/inject.js 
FOOBAR Error: ENOENT: no such file or directory, open '/home/one/github/resume/toolchain/app/index.html'