承诺同步方法

Alv*_*vin 1 asynchronous node.js promise es6-promise

我可以通过使用promise将同步方法转换为异步方法吗?

例如同步读取文件(是的fs.readFile,有回调):

// Synchronous read
var data = fs.readFileSync('input.txt'); 
Run Code Online (Sandbox Code Playgroud)

我应该这样做吗?

function readFileAsync(){
    return new Promise((resolve, reject) => {
        try {
          resolve(fs.readFileSync('input.txt')); 
        } catch(err) {
          reject(err);
        }
    })
}
Run Code Online (Sandbox Code Playgroud)

或使用异步/等待:

 function async readFileAsync(){
            try {
              let result = await fs.readFileSync('input.txt'); 
              return result;
            } catch(err) {
              return err;
            }
        })
    }
Run Code Online (Sandbox Code Playgroud)

fla*_*usa 5

TL; DR NO,不允许使用纯同步功能以避免阻塞

否。要使方法易于实现,它必须已经是异步的,即立即返回,并且在完成时还使用回调。

例如:

function loop1000() {
  for (let i = 0; i < 1000; ++i) {}
}
Run Code Online (Sandbox Code Playgroud)

不可更改,因为它不会立即返回并且不使用回调。但

function loop1000(err, callback) {
  process.nextTick(() => {
    for (let i = 0; i < 1000; ++i) { }
    callback();
  });
}
Run Code Online (Sandbox Code Playgroud)

可能是

function loop1000promisified() {
  return new Promise((resolve, reject) => loop1000(resolve));
}
Run Code Online (Sandbox Code Playgroud)

但是 所有这些方法无论如何都会在循环中阻塞。原始版本将立即被process.nextTick()阻止,使用的版本将在下一个处理器滴答时被阻止。在循环期间使应用程序无响应。

如果要使loop1000()异步友好,可以将其重写为:

function loop1000(err, callback) {
  const segmentDuration = 10;
  const loopEnd = 1000;
  let i = 0;
  function computeSegment() {
    for (let segment = 0; 
         segment < segmentDuration && i < loopEnd;
         ++segment, ++i) { }
    if (i == loopEnd) {
      callback();
      return;
    }
    process.nextTick(computeSegment);
  }
  computeSegment();
}
Run Code Online (Sandbox Code Playgroud)

因此,代替更长的阻塞时间,它将具有几个更小的阻塞。然后,约定的版本loop1000promisified()可能会有些道理。

免责声明:直接在无测试的情况下键入的代码。