함수가 비동기인지 어떻게 알 수 있습니까?
함수를 다른 함수로 넘겨 콜백으로 실행해야 합니다.문제는 이 함수가 다음과 같이 비동기식인 경우가 있다는 것입니다.
async function() {
// Some async actions
}
그래서 나는 실행하고 싶습니다.await callback()
또는callback()
수신하는 함수의 유형에 따라 달라집니다.
기능의 종류를 알 수 있는 방법이 있습니까?
이론.
네브티이async
문자열로 변환할 때 함수를 식별할 수 있습니다.
asyncFn[Symbol.toStringTag] === 'AsyncFunction'
또는 생성자별:
const AsyncFunction = (async () => {}).constructor;
asyncFn instanceof AsyncFunction === true
Babel/TypeScript를 지원하지 다음과 같은 이유 때문입니다.asyncFn
이며, transfiled code의 입니다.Function
또는GeneratorFunction
,것은 아니다.AsyncFunction
트랜스페일 코드에서 제너레이터 및 정규 함수에 대해 잘못된 긍정을 제공하지 않도록 하려면 다음과 같이 하십시오.
const AsyncFunction = (async () => {}).constructor;
const GeneratorFunction = (function* () => {}).constructor;
(asyncFn instanceof AsyncFunction && AsyncFunction !== Function && AsyncFunction !== GeneratorFunction) === true
네이티브부터async
2017년에 Node.되었으며, 이은 2017년 Node.js의 것입니다.async
transfile에 의존하는 함수async
제너레이터 함수에 사용할 수도 있습니다. 또한 제너레이터를 정규 함수로 변환하는 데 사용할 수도 있습니다.
의 결과async
함수 호출은 약속입니다.제안에 따르면, 약속 또는 비약속은 다음에게 전달될 수 있습니다.await
,그렇게await callback()
보편적입니다.
이것이 필요할 수도 있는 경우는 거의 없습니다.를 들어, 네이티브 예들어네브티이를브▁native▁for티네.async
하고 글로벌 약속을 선택하지 Promise
구현이 변경된 경우:
let NativePromise = Promise;
Promise = CustomPromiseImplementation;
Promise.resolve() instanceof Promise === true
(async () => {})() instanceof Promise === false;
(async () => {})() instanceof NativePromise === true;
이는 함수 동작에 영향을 미칠 수 있습니다(이것은 Angular 및 Zone.js 약속 구현에 대해 알려진 문제입니다).그래도 함수 반환 값이 예상되지 않음을 감지하는 것이 좋습니다.Promise
함수가 다음과 같은 것을 감지하는 대신 인스턴스async
동일한 문제가 단지 약속 이행을 대체하는 어떤 기능에도 적용될 수 있기 때문입니다.async
(해당 각도 문제에 대한 해결책은 포장하는 것입니다.async
을 반환합니다.Promise.resolve
).
연습
밖서보면에,.async
함수는 무조건 네이티브 약속을 반환하는 함수일 뿐이므로 이 함수는 네이티브 약속처럼 취급되어야 합니다.가 된 적이 async
그것은 어느 시점에서 증폭될 수 있고 규칙적인 기능이 될 수 있습니다.
약속을 돌려줄 수 있는 함수
약속을 는 ES6와 함께 할 수 .Promise.resolve
오류 허용) 래핑(동기오류허용됨래)Promise
생성자(동기화 오류 발생):
Promise.resolve(fnThatPossiblyReturnsAPromise())
.then(result => ...);
new Promise(resolve => resolve(fnThatPossiblyReturnsAPromiseOrThrows()))
.then(result => ...);
ES 2017에서 이 작업은 다음을 통해 수행됩니다.await
(문제의 예는 다음과 같습니다.)
let result = await fnThatPossiblyReturnsAPromiseOrThrows();
...
약속을 반환해야 하는 함수
어떤 물건이 약속인지 확인하는 것은 별개의 문제이지만, 일반적으로 코너 케이스를 다루기 위해 너무 엄격하거나 느슨해서는 안 됩니다.instanceof Promise
글로벌인 경우 작동하지 않을 수 있음Promise
대되었니다.Promise !== (async () => {})().constructor
이 문제는 Angular 및 Non-Angular 응용 프로그램이 인터페이스할 때 발생할 수 있습니다.
▁be가 되어야 하는 입니다.async
을 되돌리려면 먼저합니다.
let promise = fnThatShouldReturnAPromise();
if (promise && typeof promise.then === 'function' && promise[Symbol.toStringTag] === 'Promise') {
// is compliant native promise implementation
} else {
throw new Error('async function expected');
}
TL;DR:async
함수는 약속을 반환하는 일반 함수와 구별되어서는 안 됩니다.의 전갈을 할 수 인 이유가 .async
기능들.
네이티브 비동기 기능만 사용되는 한(일반적으로 해당), 저는 다음과 같은 간단한 방법을 선호합니다.
theFunc.constructor.name == 'AsyncFunction'
@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*
);
}
이것은 매우 타당한 질문이고, 저는 누군가가 그를 부결시킨 것에 화가 납니다.이러한 유형의 검사의 주요 사용 사례는 라이브러리/프레임워크/데코레이터입니다.
이것은 초기 단계이며, 우리는 유효한 질문을 부결시켜서는 안 됩니다.
노드를 사용하는 경우JS 10.x 이상
Native util 함수를 사용합니다.
util.types.isAsyncFunction(function foo() {}); // Returns false
util.types.isAsyncFunction(async function foo() {}); // Returns true
그러나 위의 답변에서 나온 모든 우려 사항을 염두에 두십시오.실수로 약속을 반환하는 함수는 잘못된 부정을 반환합니다.
그리고 그 위에 (문서에서):
이것은 JavaScript 엔진이 보고하는 내용만 보고합니다. 특히 변환 도구가 사용된 경우 반환 값이 원래 소스 코드와 일치하지 않을 수 있습니다.
하지만 만약 당신이async
JS 10이고 세배는 없습니다.이것은 좋은 해결책입니다.
는 것 같습니다.await
일반 기능에도 사용할 수 있습니다.이 " 관행 수 : "좋은 관행", "좋은 관행", "좋은 관행".
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()
다음은 David Walsh가 블로그 게시물에서 제공한 짧고 유용한 접근 방식입니다.
const isAsync = myFunction.constructor.name === "AsyncFunction";
건배!
TL;DR
단답: 사용instaceof
폭로한 후에 AsyncFunction
아래를 참조하십시오.
긴 답변:그러지 마십시오. 아래를 참조하십시오.
방법
다을사용여함선여감수있부습다니지할를지언는었되음수가로 어떤 를 감지할 수 .async
함수를 만들 때 함수 유형으로 표시됩니다. 함수:
> f1 = function () {};
[Function: f1]
테할수 다있니로 할 수 .instanceof
연산자:
> f1 instanceof Function
true
비동기 함수를 만들면 비동기 함수 유형으로 표시됩니다.
> f2 = async function () {}
[AsyncFunction: f2]
그래서 누군가는 그것을 테스트할 수 있다고 기대할 수 있습니다.instanceof
또한:
> f2 instanceof AsyncFunction
ReferenceError: AsyncFunction is not defined
왜 그런 것일까요?비동기 함수가 글로벌 개체가 아니기 때문입니다.문서 참조:
보시다시피, 아래에 나열되어 있습니다.Reference/Global_Objects
...
에쉽액야하경는우해스에 쉽게 접근할 수 경우AsyncFunction
그러면 내 것을 사용할 수 있습니다.unexposed
모듈:
로컬 변수를 가져오려면:
const { AsyncFunction } = require('unexposed');
또벌글추가를 합니다.AsyncFunction
다른 글로벌 객체와 함께:
require('unexposed').addGlobals();
이제 위의 내용이 예상대로 작동합니다.
> f2 = async function () {}
[AsyncFunction: f2]
> f2 instanceof AsyncFunction
true
하지 말아야 하는 이유
위의 코드는 함수가 다음을 사용하여 생성되었는지 여부를 테스트합니다.async
키워드를 지정하지만 정말 중요한 것은 함수가 어떻게 만들어졌는지가 아니라 함수가 약속을 반환하는지 여부입니다.
이 "비동기화" 기능을 사용할 수 있는 모든 곳:
const f1 = async () => {
// ...
};
다음을 사용할 수도 있습니다.
const f2 = () => new Promise((resolve, reject) => {
});
비록 그것이 그것과 함께 만들어지지 않았지만.async
이므로 키드이므일않습니다지하치로워다와 .instanceof
또는 다른 답변에 게시된 다른 방법을 사용합니다.
구체적으로 다음 사항을 고려합니다.
const f1 = async (x) => {
// ...
};
const f2 = () => f1(123);
그f2
당한입니다.f1
드코주함그께리추고것가는다않은니습되말지이별을 추가하는 것은 의미가 없습니다.async
여기서, 비록 결과가 만큼 "skc"가 될 것이지만.f1
모든 점에서
요약
따라서 기능이 생성되었는지 확인할 수 있습니다.async
키워드입니다. 하지만 확인할 때 잘못된 행동을 하고 있을 가능성이 높기 때문에 주의해서 사용하십시오.
따라서 수신 중인 함수의 유형에 따라 wait callback() 또는 callback()을 실행하려고 합니다.
당신은 언든지실수있다니습할행제로 할 수 .await
그리고 그것은 옳은 일을 할 것입니다.
async function main(callback) {
let result = await callback(); // even if callback is not async
// use 'result'
}
기능의 종류를 알 수 있는 방법이 있습니까?
아마도 여러분이 실제로 관심을 가지고 있는 것은 기능의 결과 유형일 것입니다.다리우스 필리피악의 대답은 좋지만 훨씬 더 간결할 수 있습니다.
async function main(callback) {
let result = callback();
if (result instanceof Promise) {
result = await result;
}
// use 'result'
}
처음에는 콜백이 약속이라고 가정할 수 있습니다.
export async function runSyncOrAsync(callback: Function) {
let promisOrValue = callback()
if (promisOrValue instanceof Promise) {
promisOrValue = Promise.resolve(promisOrValue)
}
return promisOrValue;
}
코드에서 다음과 같은 작업을 수행할 수 있습니다.
await runSyncOrAsync(callback)
알 수 없는 콜백 유형의 문제를 해결할 수 있습니다.
전체 솔루션:비동기 및 약속 모두 처리
저는 Promise와 async/wait는 기본적으로 동일하기 때문에 항상 호환적으로 사용합니다.
비동기/Await는 비동기 함수에서 약속을 처리하는 데 사용됩니다.그것은 기본적으로 약속을 위한 통사적인 설탕입니다.그것은 단지 코드를 다시 만들고 약속을 읽고 사용하기 쉽게 만들기 위한 포장지일 뿐입니다.출처:괴짜를 위한 괴짜들
값이 호출되지 않고 비동기 함수인지 확인하기 위해 도우미 함수가 필요하거나 값이 약속을 반환하는 함수인지 확인하려면 올바른 게시물에 도착했습니다.
이 예에서 저는 세 가지 다른 접근법을 제시할 것입니다.
- 함수가 비동기/대기 함수인지 확인합니다.
- 정규 함수가 Promise를 반환하는지 확인합니다.
- 둘 다 확인하세요.
비동기 함수 처리
는 이함다사용함여수정가여수있확다습니인부할를의를 하여 함수가 할 수 .async
키워드
검증할 함수의 예
async function a() {}
const b = async () => {}
유효성 검사 함수
function isAsyncFunction(f: unknown): boolean {
return f && f.constructor.name === 'AsyncFunction'
}
약속 함수 처리
이 함수는 정규 함수가 약속을 반환하는지 여부를 확인할 수 있습니다.주어진 함수가 Promise를 반환하는지 여부를 평가하려면 함수를 호출하고 반환된 값을 조사해야 합니다.동일한 기능의 다중 호출을 방지하기 위하여, 약속이면 위와 같은 값을 반환할 수 있으며,false
그렇지 않다면.
검증할 함수의 예
function a() { return new Promise(() => {}) }
const b = () => new Promise(() => {})
유효성 검사 함수
function isPromiseFunction<T>(fn: any, ...params: any[]): Promise<T> | boolean {
const isFunction = fn && typeof fn === 'function'
const notAsyncFunction = fn.constructor.name !== 'AsyncFunction'
if (isFunction && notAsyncFunction) {
const value = fn(...params) || false
if (value && value.constructor.name === 'Promise') {
return value as Promise<T>
}
}
return false
}
두 가지 모두 처리
비동기 함수와 약속은 기본적으로 동일하기 때문에 둘 다 약속을 반환하는지 확인할 수 있습니다.
function isAsync<T>(fn: any, ...params: any[]): Promise<T> | boolean {
const isFunction = fn && typeof fn === 'function'
if (isFunction) {
const value = fn(...params) || false
if (value && value.constructor.name === 'Promise') {
return value as Promise<T>
}
}
return false
}
결론
비동기식 기능은 검증이 더 빠르고 깨끗하지만, 약속 기능은 검증을 위해 호출되어야 합니다.
테스트 기능(CodePen
https://codepen.io/isakhauge/pen/gOGGQPY
하는 대신에, (되는 함수가 비동기 함수인지 테스트하는 입니다.)Promise
), , , , 를 수 await
반환된 값이 약속인지 확인한 후에만 확인합니다.
let result = someFunctionWhichMayBeAsync()
if (typeof result?.then === 'function') {
result = await result
}
이 접근법은 진정한 비동기 함수와 함께 작동할 것이며, 다음을 반환하는 모든 것.Promise
(또는 테이블).유일한 경고는 다음 값을 가진 값이 반환될 경우 실패할 수 있다는 것입니다..then
실제로 테이블이 아닌 메서드(하지만 호출도 마찬가지입니다.await
또는Promise.resolve()
그 상황에서는 무조건적으로, 그래서 당신이 할 수 있는 더 좋은 것은 없습니다.).
FWIW 단순한 것 이상으로 성능이 좋지 않을 수 있습니다.await
값을 확인하는 것처럼, 무조건 반환 값을 ing합니다..then
의 헤 드 보 있 수 습 니 다 비 쌀 더 다 오 버 ▁of 니 ▁be ▁the ▁overhead ▁might ▁than 다 ▁more ▁ 습 있 수 비쌀await
여기 벤치마크가 있습니다.
언급URL : https://stackoverflow.com/questions/38508420/how-to-know-if-a-function-is-async
'source' 카테고리의 다른 글
봇맨 대화가 mysql db에 데이터를 저장하지 않습니다. (0) | 2023.08.10 |
---|---|
strto 시간과 날짜를 사용하여 현재와 비교하여 이전 달과 연도를 얻는 방법은 무엇입니까? (0) | 2023.08.10 |
jQuery에서 $.proxy() 이해 (0) | 2023.08.10 |
드라이버 클래스 oracle.jdbc를 로드하지 못했습니다.HikariConfig 클래스 로더 또는 스레드 컨텍스트의 OracleDriver (0) | 2023.08.10 |
노드에서 줄 바꿈('\n')으로 문자열을 분할하는 방법은 무엇입니까? (0) | 2023.08.10 |