【问题标题】:nodejs write synchronous functions eg fs.readFileSyncnodejs 编写同步函数,例如 fs.readFileSync
【发布时间】:2019-01-19 20:42:13
【问题描述】:

我想创建从数据库中获取数据的函数,例如executeQuery(sql)。但我不想从此函数返回任何承诺,也不想传递任何回调函数。我只想返回查询的结果。

例如:

var rows = executeQuery('SELECT * FROM table');
console.log('database query completed:', rows);

我知道这不是 javascript 的工作方式。我还经历了许多也想要这个东西的stackoverflow问题。但是大家都说没办法。

现在这是我的问题,如果这不可能,那么像 fs.readFileSync() 这样的函数是如何工作的。这些函数既不需要任何回调,也不需要返回任何承诺。他们只是做他们被定义做的事情。

【问题讨论】:

标签: javascript node.js synchronous


【解决方案1】:

更新:就像@Paulpro 在 cmets 中所说,下面的这个答案永远不会起作用,因为代码将陷入无限循环。所以你最好选择 Promises


我建议像 @happy-machine 和 @bergur,最好使用 Promises。但如果你想知道fs.readFileSync() 是如何工作的,请阅读fs module code in nodejs source code

您会发现它执行do {} while() 并且您可以执行相同的操作 像这样同步你的异步代码

var rows;
executeQuery('SELECT * FROM table').then(
  promiseResponse => {
   rows = promiseResponse
  }
)
do {
  // nothing
} while(!rows) // rows is undefined
console.log('database query completed:', rows);

【讨论】:

  • 这有一个不修改rows的无限循环,它永远无法到达console.log行。
  • 我将答案编辑为箭头函数,它会改变行
  • 箭头函数永远不会运行,因为有一个无限循环在运行。
  • 试试var rows; setTimeout( _ => { rows = true; }, 100 ); do {} while (! rows); console.log('never reached'); 看看我的意思。
【解决方案2】:

fs.readFileSync() 可以是同步的,因为它只是与您的本地文件系统一起工作,这可能是一个快速操作。如果你的数据库是本地的,它也可以被写成同步的。但是,如果您的数据库在网络上,executeQuery 将不得不发送一个 http 请求并等待响应,这可能需要很长时间并且可能由于以下原因而无法同步:

注意:从 Gecko 30.0(Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27)开始,由于对用户体验的负面影响,主线程上的同步请求已被弃用。

【讨论】:

    【解决方案3】:

    您可以使用异步/等待。这将为您提供与 readFileSync 几乎相同的语法——即没有承诺链或回调。

    var rows = await executeQuery('SELECT * FROM table')
    console.log('database query completed:', rows) // this now works
    

    您只需将其包装在异步函数中即可。

    只是为了避免混淆。该函数仍然是异步的,它只是让代码更容易阅读的语法糖。

    【讨论】:

    【解决方案4】:

    同步是同步的,在完成之前会阻塞执行。 fs 的 Sync 方法将其结果作为返回值返回。

    其他 fs 非同步方法是异步的,并在它们在后台运行时立即返回。你传递了一个回调函数,当它们完成时会被调用。

    当您开始使用 Javascript 时,Promises 有点像噩梦,但是因为 Javascript 只有一个线程,所以一旦您习惯了它们,它们就会成为 Javascript 之美的一部分。如果您使用 Sync 函数,您会阻塞线程,这通常不是一个好主意,尤其是在您不使用工作线程时。

    如果你想在这里查看的话,我写了一篇关于围绕 Promise 包装你的帖子

    Why Does Async Always Return a Promise?

    【讨论】:

    • 对不起。但这不是我要问的。我知道如何使用承诺和回调。但我不想使用它们
    • 但是你不能真正避免它们.. javascript 的全部意义在于它是异步的。在从数据库中获取数据时,您不能阻塞线程。而你却因为试图帮助你看到这一点而贬低我!如果您编写的代码是同步构建的,那么 Web 将无法正常工作。
    • 如果你坚持阻塞线程,有同步 mysql 库github.com/Will-I4M/node-mysql-libmysqlclient 你将无法对大多数提供阻塞方法的库进行同步调用.. 这是不好的做法
    猜你喜欢
    • 1970-01-01
    • 2016-07-02
    • 2013-11-06
    • 1970-01-01
    • 2021-12-19
    • 1970-01-01
    • 2021-12-31
    • 2017-04-28
    相关资源
    最近更新 更多