确定方法是同步还是异步

And*_*een 16 javascript node.js

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

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

function isSynchonous(methodName) {
    //if the method is synchronous, return true. Otherwise, return false.
}
Run Code Online (Sandbox Code Playgroud)

dje*_*lin 7

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

  • 函数可以异步执行,但同步返回某些内容; 比如说,返回被触发的异步任务的数量.
  • 函数可以同步返回表示异步信息的promises.我会称这样的方法是异步的,但语言无法真正说明这一点.
  • 在一些反常的意义上,每个异步函数"返回"某些东西...... undefined如果没有别的话.

从工程角度来看:

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

此外,有两种功能可以混合使用.

function(callback) {
    if(ready) {
        callback();
    }
    else {
        setTimeout(callback, 5000);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

if(ready) {
    process.nextTick(callback);
}
Run Code Online (Sandbox Code Playgroud)

所以函数具有统一的行为.

然而,有一个哈克的方式来告诉如果有什么异步发生,至少在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.");
}
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为根据定义,异步工作无法在同一个tick上解析,并且因为Node.js是单线程的.


lla*_*bda 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.') });
Run Code Online (Sandbox Code Playgroud)

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


Ry-*_*Ry- 3

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