programing

함수가 비동기인지 어떻게 알 수 있습니까?

sourcetip 2021. 1. 14. 23:43
반응형

함수가 비동기인지 어떻게 알 수 있습니까?


다른 함수에 함수를 전달하고 콜백으로 실행해야합니다. 문제는 때때로이 함수가 다음과 같이 비동기 적이라는 것입니다.

async function() {
 // Some async actions
}

그래서 나는 실행 await callback()하거나 callback()수신하는 기능의 유형에 따라 실행하고 싶습니다 .

기능의 유형을 아는 방법이 있습니까 ??


기본 async함수는 문자열로 변환 될 때 식별 수 있습니다 .

asyncFn[Symbol.toStringTag] === 'AsyncFunction'

또는 AsyncFunction생성자 :

const AsyncFunction = (async () => {}).constructor;

asyncFn instanceof AsyncFunction === true

이 때문에, 바벨 / 타이프 라이터 출력 작동하지 않습니다 asyncFntranspiled 코드에서 일정한 기능, 그것은의 인스턴스 Function또는 GeneratorFunction하지 AsyncFunction. 트랜스 파일 된 코드의 제너레이터 및 일반 함수에 대해 오 탐지 여부확인하려면 :

const AsyncFunction = (async () => {}).constructor;
const GeneratorFunction = (function* () => {}).constructor;

(asyncFn instanceof AsyncFunction && AsyncFunction !== Function && AsyncFunction !== GeneratorFunction) === true

이 질문은 분명히 Babel의 async함수 구현을 의미하며 , 생성기 함수 transform-async-to-generator로 트랜스 파일 하는 데 의존하며 제너레이터를 일반 함수로 트랜스 파일 async하는 transform-regenerator사용할 수도 있습니다 .

async함수 호출 의 결과 는 약속입니다. 제안에 따르면 약속 또는 비 약속이로 전달 될 수 await있으므로 await callback()보편적입니다.

이것이 필요할 수있는 경우는 거의 없습니다. 예를 들어, 네이티브 async함수는 내부적으로 네이티브 프라 미스를 사용 Promise하고 구현이 변경된 경우 전역을 선택하지 않습니다 .

let NativePromise = Promise;
Promise = CustomPromiseImplementation;

Promise.resolve() instanceof Promise === true
(async () => {})() instanceof Promise === false;
(async () => {})() instanceof NativePromise === true;

이는 함수 동작에 영향을 미칠 수 있습니다 (이것은 Angular 및 Zone.js promise 구현에 대해 알려진 문제입니다 ). 그럼에도 불구 Promise하고 함수가임을 감지하는 대신 함수 반환 값이 예상 인스턴스 가 아니라는 것을 감지하는 것이 바람직합니다 async. 왜냐하면 동일한 문제가 대체 약속 구현을 사용하는 모든 함수에 적용 가능하기 때문입니다 async( 상기 Angular 문제에 대한 해결책asyncreturn 을 래핑하는 것입니다). Promise.resolve).

요약 : async함수는 프라 미스 를 반환하는 일반 함수와 구별되어서는 안됩니다. 이런 상황에서 그들은 확실히 구별되어서는 안됩니다. 신뢰할 수있는 방법과 비 네이티브 트랜스 파일 async함수 를 감지 할 이유가 없습니다 .


@rnd와 @estus가 모두 정확합니다.

그러나 실제 작동하는 솔루션으로 질문에 답하려면

function isAsync (func) {
    const string = func.toString().trim();

    return !!(
        // native
        string.match(/^async /) ||
        // babel (this may change, but hey...)
        string.match(/return _ref[^\.]*\.apply/)
        // insert your other dirty transpiler check

        // there are other more complex situations that maybe require you to check the return line for a *promise*
    );
}

이것은 매우 타당한 질문이며, 누군가가 그에게 투표했다는 사실에 화가났습니다. 이러한 유형의 검사에 대한 주요 사용 사례는 라이브러리 / 프레임 워크 / 데코레이터입니다.

지금은 초기 단계이므로 유효한 질문에 반대 투표를 해서는 안됩니다 .


이 간단한 방법을 선호합니다.

theFunc.constructor.name == 'AsyncFunction'

NodeJS 10.x 이상을 사용하는 경우

기본 util 함수를 사용합니다 .

   util.types.isAsyncFunction(function foo() {});  // Returns false
   util.types.isAsyncFunction(async function foo() {});  // Returns true

그래도 위에서 모든 우려 사항을 염두에 두십시오. 우연히 약속을 반환하는 함수는 거짓 부정을 반환합니다.

그리고 그 위에 (문서에서) :

이것은 JavaScript 엔진이보고있는 것만보고한다는 점에 유의하십시오. 특히 트랜스 파일 도구를 사용한 경우 반환 값이 원본 소스 코드와 일치하지 않을 수 있습니다.

그러나 asyncNodeJS 10에서 사용 하고 변환하지 않는 경우. 이것은 좋은 해결책입니다.


TL; DR

짧은 답변 : 노출instaceof사용 -아래 참조. AsyncFunction

긴 대답 : 그렇게하지 마십시오. 아래를 참조하십시오.

그것을하는 방법

함수가 async키워드 로 선언되었는지 여부를 감지 할 수 있습니다.

함수를 만들면 함수 유형이 표시됩니다.

> f1 = function () {};
[Function: f1]

instanceof운영자 와 함께 테스트 할 수 있습니다 .

> f1 instanceof Function
true

비동기 함수를 생성하면 AsyncFunction 유형이 표시됩니다.

> f2 = async function () {}
[AsyncFunction: f2]

따라서 다음과 instanceof같이 테스트 할 수도 있습니다 .

> f2 instanceof AsyncFunction
ReferenceError: AsyncFunction is not defined

왜 그런 겁니까? AsyncFunction은 전역 개체가 아니기 때문입니다. 문서를 참조하십시오.

보시다시피 Reference/Global_Objects... 아래에 나열되어 있습니다 .

If you need easy access to the AsyncFunction then you can use my unexposed module:

to get either a local variable:

const { AsyncFunction } = require('unexposed');

or to add a global AsyncFunction alongside other global objects:

require('unexposed').addGlobals();

and now the above works as expected:

> f2 = async function () {}
[AsyncFunction: f2]
> f2 instanceof AsyncFunction
true

Why you shouldn't do it

The above code will test whether the function was created with the async keyword but keep in mind that what is really important is not how a function was created but whether or not a function returns a promise.

Everywhere where you can use this "async" function:

const f1 = async () => {
  // ...
};

you could also use this:

const f2 = () => new Promise((resolve, reject) => {
});

even though it was not created with the async keyword and thus will not be matched with instanceof or with any other method posted in other answers.

Specifically, consider this:

const f1 = async (x) => {
  // ...
};

const f2 = () => f1(123);

The f2 is just f1 with hardcoded argument and it doesn't make much sense to add async here, even though the result will be as much "async" as f1 in every respect.

Summary

So it is possible to check if a function was created with the async keyword, but use it with caution because you when you check it then most likely you're doing something wrong.


It seems that await can be used for normal functions too. I'm not sure if it can be considered "good practice" but here it is:

async function asyncFn() {
  // await for some async stuff
  return 'hello from asyncFn' 
}

function syncFn() {
  return 'hello from syncFn'
}

async function run() {
  console.log(await asyncFn()) // 'hello from asyncFn'
  console.log(await syncFn()) // 'hello from syncFn'
}

run()

Hei,

Here is an approach provided by David Walsh in his blogpost:

const isAsync = myFunction.constructor.name === "AsyncFunction";

Cheers!


You can assume at begin that callback is promise:

export async function runSyncOrAsync(callback: Function) {

  let promisOrValue = callback()
  if (promisOrValue instanceof Promise) {
    promisOrValue = Promise.resolve(promisOrValue)
  }
  return promisOrValue;
}

and them in your code you can do this:

await runSyncOrAsync(callback)

which will solve your problem with unknowing callback type....

ReferenceURL : https://stackoverflow.com/questions/38508420/how-to-know-if-a-function-is-async

반응형