비동기 함수 외부에서 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.