20

在 node.js 中,是否可以确定(使用函数)方法是同步的还是异步的?

我想编写一个执行以下操作的函数:

function isSynchonous(methodName) {
    //if the method is synchronous, return true. Otherwise, return false.
}
4

4 回答 4

8

从语言的角度来看,这是不可能的,我相信 llambda 的回答证明了这一点。

  • 函数可以异步做事但同步返回一些东西;比如说,返回被触发的异步任务的数量。
  • 函数可以同步返回代表异步信息的承诺。我会称这种方法为异步的,但语言无法真正说明这一点。
  • 在某种反常的意义上,每个异步函数都会“返回”一些东西……undefined如果没有别的。

从工程的角度来看:

  • 阅读文档。
  • 如果函数接受回调,它很可能是异步的。查看函数签名。
  • 阅读代码。
  • 使用“常识”。如果函数执行 IO 并从 IO 返回结果,则在某些情况下,它必须是异步的。这包括文件读取、从标准输入读取、保存到数据库和 HTTP/AJAX 请求。注意流通常用于此,它表示异步任务,但回调是特殊的。

此外,还有两者混合的功能。

function(callback) {
    if(ready) {
        callback();
    }
    else {
        setTimeout(callback, 5000);
    }
}

可以说这是非常邪恶的,正确的做法是

if(ready) {
    process.nextTick(callback);
}

所以该函数具有统一的行为。

但是,至少在 Node.js 中,有一种方法可以判断是否发生了任何异步事件。请参阅此讨论

// untested!! please read the documentation on these functions before using yourself
var work = process._getActiveHandles().length + process._getActiveCallbacks().length;
foo;
var newWork = (process._getActiveHandles().length + process._getActiveCallbacks().length) - work;
if(newWork > 0) {
    console.log("asynchronous work took place.");
}

这是可行的,因为根据定义,异步工作不能在同一个滴答上解决,并且因为 Node.js 是单线程的。

于 2014-08-19T16:59:24.627 回答
5

你不一定知道。一个函数甚至可以是随机同步或异步的。

例如,一个接受另一个函数的函数可以立即执行该函数,或者它可以使用 setImmediate 或 nextTick 安排在以后执行它。该函数甚至可以随机选择同步或异步调用其传递的函数,例如:

console.log('Start')

function maybeSynchOrAsync(fun) {

  var rand = Math.floor((Math.random() * 2))

  if (rand == 0) {
    console.log('Executing passed function synchronously')
    fun()
    console.log('Done.')
  } else {
    console.log('Executing passed function asynchronously via setImmediate')
    setImmediate(fun)
    console.log('Done.')
  }
}

maybeSynchOrAsync(function () { console.log('The passed function has executed.') });

此外,从技术上讲,每个函数调用都是同步的。如果您调用函数F,并且F将回调函数排队等待稍后调用(使用 setTimeout 或任何机制),则原始函数F仍然具有同步返回值(无论它是未定义的、承诺的、thunk 还是其他)。

于 2014-08-19T16:54:24.527 回答
3

不,那是不可能的。这些方法不仅标记为同步或异步,它们要么使用回调,要么不使用。

于 2012-10-01T20:08:59.047 回答
2

为什么你需要知道,是真正的问题。

话说回来; 这可以通过新的 JS 抽象来实现。如今,对于由前面的关键字明确定义的异步函数,async您可以执行如下测试;

async function test(){}
var type = Object.getPrototypeOf(test).constructor.name;
console.log(type); // <- 'AsyncFunction'

凉爽的..!

至于那些碰巧返回一个promise的普通函数,我们必须记住它只是一个同步函数立即同步返回一个promise对象。这意味着您必须在调用函数之前动态检查函数是否提前返回承诺。我认为这将带您进入类型级别的编程冒险,这种冒险存在于 Haskell 等复杂语言中。

于 2021-11-17T21:03:24.070 回答