비동기 함수 외부에서 await 사용


85

첫 번째에는 두 번째가 모듈을 실행하거나 종료하도록하는 조건부 반환 매개 변수가 있기 때문에 두 개의 비동기 함수를 함께 연결하려고했습니다. 그러나 사양에서 찾을 수없는 이상한 동작을 발견했습니다.

async function isInLobby() {
    //promise.all([chained methods here])
    let exit = false;
    if (someCondition) exit = true;
}

이것은 내 코드 ( 여기 에서 전체 범위를 볼 수 있음)의 멍청한 스 니펫으로 , 플레이어가 이미 로비에 있는지 확인하기 만하면되지만 관련이 없습니다.

다음으로이 비동기 함수가 있습니다.

async function countPlayer() {
    const keyLength = await scardAsync(game);
    return keyLength;
}

이 함수는 exit === true.

나는하려고했다

const inLobby = await isInLobby();

이것은 결과를 기다리고 싶었으므로 inLobby조건부로 실행할 수 countPlayer있지만 특정 세부 사항이없는 유형 오류가 발생했습니다.

수없는 이유는 당신 기능의 범위의 기능 밖에? 나는 그것이 설탕 약속이라는 것을 압니다. 그래서 그것은 연결 되어야만합니다. 그러나 그것은 왜 내가 다른 약속을 기다릴 수 있지만 밖에서는 할 수없는 이유 입니까?awaitasyncthencountPlayerawait isInLobby


당신이했던 곳await isInLobby() 과 어떻게 inLobby사용 되는지 보여줄 수 있습니까 ? 또한, 어디 / 어떻게 countPlayer호출됩니까?
— Bergi

@Bergi 실제 컨텍스트를 위해 내 저장소를 연결했습니다. 너무 많은 코드는 질문에 넣어
— 스털링 아처에게

문제가 어디에 있는지 모르겠습니다 (이미 저장소를 업데이트했을 수도 있습니다)? isInLobby().then( … countPlayer().then …부품 을 참조 하면 해결 방법은 간단합니다. 해당 호출이 포함 된 함수 ( (req, res) =>하나)를 만드십시오 async.
— Bergi

@Bergi 문제는 깨진 것이 아니라 그대로 작동합니다. 나는 왜 최고 수준의 기다림이 문제가 아닌지 이해하지 못했습니다. 그것은 밝혀 그냥 비동기 함수로 전체 모듈을 범위 지정하지 않고 아직 존재 아니에요
— 스털링 아처를

그러나 코드에 대해 최상위 수준 이 전혀 필요하지 await않습니까? 그렇기 때문에 질문의 문제와 실제로 관련이없는 답변을 받아들 였는지 궁금했습니다.
— Bergi

답변:


73

최상위 수준 await은 지원되지 않습니다. 이 Github 문제 와 같은 이유에 대한 표준위원회의 몇 가지 토론 이 있습니다.

Github 에는 최상위 수준이 왜 나쁜 생각인지에 대한 생각이 있습니다. 특히 그는 다음과 같은 코드가있는 경우 다음과 같이 제안합니다.

// data.js
const data = await fetch( '/data.json' );
export default data;

이제 가져 오는 파일은 가져 오기 가 완료 될 때까지 실행되지 않으므로 이제 모든data.js 모듈로드가 차단됩니다. 이것은 우리가 동기적이고 예측 가능한 최상위 자바 스크립트 실행에 익숙하기 때문에 앱 모듈 순서를 추론하기 매우 어렵게 만듭니다. 이것이 허용되면 함수가 언제 정의되는지 아는 것이 까다로워집니다.

내 관점 은 모듈을로드하는 것만으로도 부작용이 발생하는 것은 나쁜 습관이라는 것입니다. 즉, 모듈의 모든 소비자는 단순히 모듈을 요구함으로써 부작용을 얻을 수 있습니다. 이것은 모듈을 사용할 수있는 위치를 심하게 제한합니다. 최상위 수준은 await아마도 일부 API에서 읽거나 로드시 일부 서비스를 호출하고 있음을 의미합니다 . 대신 소비자가 자신의 속도로 사용할 수있는 비동기 함수를 내 보내야합니다.


좋은 링크입니다. 감사합니다. 아쉽게도 최고 수준의 지원이 없습니다. 그러길 바랍니다. 현재로서는 여기에 약속을해야하는데 이는 매우 나쁜 습관이며 마음에 들지 않습니다. :( 감사합니다.
— Sterling Archer

void async function() { const inLobby = await isInLobby() }()
— @SterlingArcher

@robertklep은 inLobby액세스 할 수 없도록하는 함수의 범위 가 아닙니까?
— Sterling Archer

@SterlingArcher 그렇습니다. 모든 코드를 거기 로 옮겨야 합니다 (기본적으로 "최상위 수준"으로 만듭니다). 사용하는 것의 대안 일뿐입니다 .then()(죄송합니다. 조금 더 명확하게 만들었어야합니다).
— robertklep

동의하지 마십시오. data.js 사용자는 data.js 자체와 모든 종속성을로드하는 동안 '차단'되지만 '차단'이라는 개념은 그 자체로 나쁘지 않습니다. 최상위 수준 대기는 사용이 '해제'되기 전에 필요로하는 종속성을로드하는 것으로 간주 될 수 있습니다.
— Ibrahim ben Salah

125

물론 이것은 항상 있습니다 :

(async () => {
    await ...

    // all of the script.... 

})();
// nothing else

이것은 await를 사용할 수있는 async로 빠른 기능을 만듭니다. 훌륭한 비동기 함수를 만들 필요가 없습니다! // Silve2611 크레딧


3
더 자세히 설명하고 이것이 작동하는 이유를 설명하십시오.
— Paul Back

12
이 답변에 반대 투표하는 것은 매우 어리석은 일입니다. await를 사용할 수있는 비동기로 빠른 기능을 만듭니다. 훌륭한 비동기 함수를 만들 필요가 없습니다!
— Silve2611

55
await이 익명 함수 가 여전히 필요하기 때문에 문제를 해결 하지 못합니다.이 함수는 다시 함수 외부에서 작동하지 않습니다.
— Michael

그렇다면 이것이 오류 조건을 어떻게 처리할까요? 또한 대기 코드 내부에 착륙합니까?
— Manuel Hernandez

TKS이 greate 도움이 특별히 약속은 한 번 저장 getItem를 얻기 위해 다시 완벽하게 reponse입니다 로그인 API, 가져 콜백입니다
— TESS HSU

9

더 좋은 방법은 코드 블록 앞에 세미콜론을 추가하는 것입니다.

;(async () => {
    await ...
})();

이렇게하면 자동 포맷터 (예 : vscode)가 첫 번째 괄호를 이전 줄의 끝으로 이동하는 것을 방지합니다.

다음 예제에서 문제를 설명 할 수 있습니다.

const add = x => y => x+y
const increment = add(1)
(async () => {
    await ...
})();

세미콜론이 없으면 다음과 같이 다시 형식화됩니다.

const add = x => y => x+y
const increment = add(1)(async () => {
  await Promise(1)
})()

비동기 함수를 y매개 변수 로 할당 하고 결과에서 함수를 호출하려고 시도하기 때문에 분명히 잘못된 것 입니다 (실제로 이상한 문자열입니다 '1async () => {...}')


20
잘못된 것은 개혁자가 아닙니다. 세미콜론이 없으면 런타임에 함수가 구문 분석되고 오류, 줄 바꿈 또는 줄 바꿈 없음이 발생합니다. 예제의 올바른 해결책 add(1);은 비동기 함수 앞이 아니라 뒤에 세미콜론을 추가하는 것 입니다.
— Madara 's Ghost

11
또한 이것이 당면한 질문과 어떤 관련이 있는지 솔직히 이해하지 못합니다.
— Madara 's Ghost

네 말이 맞아. 또한 런타임에는 세미콜론이 필요합니다.
— Viliam Simko


1

typescript 3.8부터 최상위 수준 대기를 수행 할 수 있습니다.
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#-top-level-await
게시물에서 :
이전에 JavaScript (비슷한 기능을 가진 대부분의 다른 언어와 함께), await는 비동기 함수의 본문 내에서만 허용되었습니다. 그러나 최상위 수준의 await를 사용하면 모듈의 최상위 수준에서 await를 사용할 수 있습니다.

const response = await fetch("...");
const greeting = await response.text();
console.log(greeting);

// Make sure we're a module
export {};

미묘한 점이 있습니다. 최상위 수준 대기는 모듈의 최상위 수준에서만 작동하며 파일은 TypeScript가 가져 오기 또는 내보내기를 찾을 때만 모듈로 간주됩니다. 일부 기본 경우에는이를 확인하기 위해 일부 상용구로 export {}를 작성해야 할 수 있습니다.

이 시점에서 예상 할 수있는 모든 환경에서 최상위 수준 대기가 작동하지 않을 수 있습니다. 현재는 대상 컴파일러 옵션이 es2017 이상이고 모듈이 esnext 또는 system 인 경우에만 최상위 수준 await를 사용할 수 있습니다. 여러 환경 및 번 들러 내에서 지원이 제한되거나 실험적 지원을 활성화해야 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.