Determine whether a method is synchronous or async

2020-06-01 02:23发布

In node.js, is it possible to determine (using a function) whether a method is synchronous or asynchronous?

I'd like to write a function that does the following:

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

3条回答
Lonely孤独者°
2楼-- · 2020-06-01 02:35

From a language standpoint this is not possible, which I believe llambda's answer proves.

  • Functions can do things asynchronously but return something synchronously; say, return the number of async tasks that were fired off.
  • Functions can synchronously return promises... that represent asynchronous information. I would call such a method asynchronous but the language can't really tell that.
  • In some perverse sense every asynchronous function "returns" something... undefined if nothing else.

From an engineering standpoint:

  • read the documentation.
  • If the function accepts a callback, it is likely asynchronous. Look at the function signature.
  • Read the code.
  • Use "common sense." If the function does IO and returns a result from IO it must be, in some case, asynchronous. This includes file reading, reading from standard input, saving to a database, and HTTP/AJAX requests. Note streams are often used for this, which represents an asynchronous task, but the callbacks are special.

Furthermore there are functions that mix the two.

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

Arguably this is very evil, and correct practice would be

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

so the function has uniform behavior.

However there is a hacky way to tell if anything asynchronous happened, at least in Node.js. See this discussion.

// 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.");
}

This works because asynchronous work cannot resolve on the same tick, by definition, and because Node.js is single threaded.

查看更多
淡お忘
3楼-- · 2020-06-01 02:46

You don't necessarily know. A function could even be randomly synchronous or asynchronous.

For example, a function that takes another function could execute that function immediately, or it could schedule to execute it at a later time using setImmediate or nextTick. The function could even randomly choose to call its passed function synchronously or asynchronous, such as:

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.') });

Further, technically speaking, every function call is synchronous. If you call a function F, and F queues a callback function to be invoked later (using setTimeout or whatever mechanism), the original function F still has a synchronous return value (whether it's undefined, a promise, a thunk, or whatever).

查看更多
▲ chillily
4楼-- · 2020-06-01 02:47

No, that's impossible. The methods aren't just marked synchronous or asynchronous, they either use callbacks or they don't.

查看更多
登录 后发表回答