Node.js调用异步函数后跟等待还是同步函数有什么优势吗?

时间:2019-01-07 04:39:25

标签: node.js

我最近在异步函数中看到了这类代码

async function foo() {
    const readFile = util.promisify(fs.readFile);
    const data = await readFile(file, 'utf8');
    // .... other code
}

是否有这样做的优势:

async function foo() {
    const data = readFileSync(file, 'utf8');
    // ... other code
}

总的来说,我感兴趣的是与调用异步函数然后在返回时立即等待相比,是否有优势,而不是调用相应的同步函数而无需等待。

并且假设这个异步功能已经被包装在一个诺言中了?

注意:一些注释和答案引用的是此代码的早期版本,该版本存在错误,并且意图不明确。

2 个答案:

答案 0 :(得分:3)

非常有效的问题的答案是:同步方法将阻塞线程,而异步方法将允许其他JavaScript在操作发生时运行,从而为您的应用程序提供更大的扩展空间。

例如,如果您编写了一个http服务器,并且每分钟仅收到一个请求,并且从未同时发出请求,那么您执行什么操作都没关系。线程仅被阻塞几毫秒,对于依赖它的请求,工作是不可避免的。但是,如果您每分钟要处理100个请求,并且可能在同一个JS应用程序中按某些cron计划进行了其他工作,则使用异步方法将允许这些请求继续通过服务器代码(JS)进行处理,文件系统的工作正在幕后完成(我相信,在C ++中,但是您必须用Google搜索这一部分)。当线程被同步函数阻塞时,所有这些请求和事件都会堆积在事件队列中,等待JS处理它们,即使JS事件循环可能并不直接忙于任何事情。 / em>这只是在等待。那不是很好,因此请尽可能利用单线程JS的异步特性。

关于错误处理,这些函数的异步版本具有一个错误对象(或成功时为null)作为回调的第一个参数,当您对其进行合理化时,该对象将传递给.catch方法。这允许自然的和内置的错误处理。您将使用*Sync函数观察到没有回调,并且如果发生错误,您将不会以有用的方式收到该错误(通常会使应用程序崩溃)。这里有两个例子来说明:

Unhelpful.js

const fs = require('fs')
const util = require('util')

const test = fs.readFileSync('./test.js') // spoiler alert: ./test.js doesn't exist

console.log('test:', test) // never runs, because the error thrown is not caught and the process exits :(

/*
Output:

fs.js:113
    throw err;
    ^

Error: ENOENT: no such file or directory, open './test.js'
    at Object.openSync (fs.js:434:3)
    at Object.readFileSync (fs.js:339:35)
    ...etc...
*/

Better.js

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

;(async function () {
  // The catch handler actually returns the error object, so test will hold
  // the value/result of the readFile operation whether it succeeds or fails
  const test = await readFile('./test.js').catch(err => err instanceof Error ? err : new Error(err))

  console.log('test:', test)
  // helpful log, as a result:
  // test: { [Error: ENOENT: no such file or directory, open './test.js'] errno: -2, code: 'ENOENT', syscall: 'open', path: './test.js' }
})()

答案 1 :(得分:0)

现在,我认为我已经了解了情况,让我尝试解释一下我的困惑。

我曾以为V8或nodejs维护了一组可运行线程,即使在给定时间只运行了一个。我也保证异步功能创建了一个新线程。因此,如果该线程被阻止,就没有问题,因为其他一些runabble线程将被交换。

根据人们发布的内容,现在我相信只有一个线程(至少对程序员可见),因此可以在任意位置阻塞 (无论是否有协程/异步函数) )阻止无处不在

相关问题