await는 비동기 함수에서만 유효합니다.


130

이 코드를 작성했습니다. lib/helper.js

var myfunction = async function(x,y) {
   ....
   reutrn [variableA, variableB]
}
exports.myfunction = myfunction;

그런 다음 다른 파일에서 사용하려고했습니다.

 var helper = require('./helper.js');   
 var start = function(a,b){
     ....
     const result = await helper.myfunction('test','test');
 }
 exports.start = start;

오류가 발생했습니다

"await는 비동기 함수에서만 유효합니다."

이슈가 뭐야?


1
문제는 함수 await내에서만 사용할 수 있다는 async것입니다. 즉, await함수를 비 동기화하므로 그렇게 선언해야합니다.
Pointy

현재 오류는 무엇입니까?
acdcjunior

여전히 동일합니다. SyntaxError : await는 비동기 함수에서만 유효합니다
j.doe

코드에 대한 더 많은 컨텍스트를 공유해야합니다.
Ele

답변:


160

오류는 참조가 myfunction아니라 start.

async function start() {
   ....

   const result = await helper.myfunction('test', 'test');
}

// My function
const myfunction = async function(x, y) {
  return [
    x,
    y,
  ];
}

// Start function
const start = async function(a, b) {
  const result = await myfunction('test', 'test');
  
  console.log(result);
}

// Call start
start();



내가 사용하여 알려진 안티 패턴에 대해 조언이 질문의 기회를 사용 await하다 : return await.


잘못된

async function myfunction() {
  console.log('Inside of myfunction');
}

// Here we wait for the myfunction to finish
// and then returns a promise that'll be waited for aswell
// It's useless to wait the myfunction to finish before to return
// we can simply returns a promise that will be resolved later

// useless async here
async function start() {
  // useless await here
  return await myfunction();
}

// Call start
(async() => {
  console.log('before start');

  await start();
  
  console.log('after start');
})();


옳은

async function myfunction() {
  console.log('Inside of myfunction');
}

// Here we wait for the myfunction to finish
// and then returns a promise that'll be waited for aswell
// It's useless to wait the myfunction to finish before to return
// we can simply returns a promise that will be resolved later

// Also point that we don't use async keyword on the function because
// we can simply returns the promise returned by myfunction
function start() {
  return myfunction();
}

// Call start
(async() => {
  console.log('before start');

  await start();
  
  console.log('after start');
})();


또한 return await정확하고 중요한 특별한 경우가 있음을 알고 있어야합니다 . (try / catch 사용)

'return await'에 성능 문제가 있습니까?


그러나 이것은 작동하지 않아 코드를 업데이트했습니다. 여전히 같은 오류가 발생합니다
j.doe

@ j.doe 스 니펫을 추가했습니다
Grégory

2
고마워, 내 문제를 발견했다. 콜백 내부에서 시도한 것은 start () 함수입니다. 해결책은 다음과 같습니다. const start = async function (a, b) {task.get (options, async function (error, result1) {const result = await myfunction ( 'test', 'test');
j.doe

노드가 단일 스레드임을 고려하십시오. 분당 요청을 줄이고 요청을 가득 채우는 사이의 지연을 증가시키지 않습니다.
Rishabh Dhiman

1
은 "올바른"예제에서 언급이의 가치, 그것을 선언 할 필요가 없습니다 startint로서 async(일부 그렇게 어쨌든 수행하기로 결정 되더라도 더 명시하기 위해) 기능
게르 솜

11

이 오류가 발생했을 때 "async"함수 내에서 map 함수를 호출 한 것으로 나타났습니다. 따라서이 오류 메시지는 실제로 "async"로 표시되지 않은 맵 함수를 참조하는 것입니다. 이 문제를 해결하려면 map 함수에서 "await"호출을 받고 예상되는 동작을 얻는 다른 방법을 생각해 냈습니다.

var myfunction = async function(x,y) {
    ....
    someArray.map(someVariable => { // <- This was the function giving the error
        return await someFunction(someVariable);
    });
}

2
이것이 저에게 문제였습니다. 나는지도 기능을 for 루프로 대체했는데, 이는 나에게 쉬운 해결책이었습니다. 그러나이 솔루션은 코드에 따라 작동하지 않을 수 있습니다.
Thomas

6
참고로 당신은 또한 할 수someArray.map(async (someVariable) => { return await someFunction(someVariable)})
ptim

1
await때문에 코드는 오해의 소지가되는 Array.map비동기 함수로 기능을 처리하지 않습니다. 명확하게 말하면, map기능이 완료된 후에 someFunction는 모두 보류 중입니다. 함수가 끝날 때까지 정말로 기다리려면 다음 await Promise.all(someArray.map(someVariable => someFunction(someVariable)))과 같이 작성해야합니다. 또는 await Promise.all(someArray.map(someFunction))).
Grégory NEUT

9

를 사용하려면 await실행 컨텍스트가 async본질적으로 있어야합니다.

말했듯이, 당신 executing contextawait무엇보다 먼저 당신이 할 일을 기꺼이하는 당신 의 성격을 정의 할 필요가 있습니다.

작업을 실행할 선언 async앞에 넣으 fn십시오 async.

var start = async function(a, b) { 
  // Your async task will execute with await
  await foo()
  console.log('I will execute after foo get either resolved/rejected')
}

설명:

귀하의 질문에 귀하는 본질적으로 병렬로 실행 method되는을 가져오고 asynchronous있습니다. 그러나 그 async메소드 를 실행하려는 곳은 사용 execution context하기 위해 정의 해야하는 다른 내부 async에 있습니다 await.

 var helper = require('./helper.js');   
 var start = async function(a,b){
     ....
     const result = await helper.myfunction('test','test');
 }
 exports.start = start;

후드 아래에서 무슨 일이 일어나고 있는지 궁금해

await약속 / 미래 / 작업 반환 방법 / 함수 async를 사용하고 await를 사용할 수있는 방법 / 함수를 표시합니다.

또한 당신은 잘 알고있는 경우 promises, await실제로 약속 / 해결의 동일한 프로세스를하고있다. 약속 체인을 만들고 resolve콜백 에서 다음 작업을 실행합니다 .

자세한 내용은 MDN DOCS를 참조하십시오 .


시작 기능에서 비동기로도 오류가 발생합니다
j.doe

어디에서 누락되고이 오류가 발생하는지 잘 모르겠습니다.이 오류를 해결하기위한 복잡한 설명은 없습니다.
Satyam Pathak

이것은 올바른 대답이며 실제로 밑줄 이유를 설명했습니다. 투표했습니다.
linehrr

3

async/ 의 현재 구현은 함수 내부의 키워드 await만 지원합니다 . 내부에서 사용할 수 있도록 함수 서명을 변경하십시오 .awaitasyncstartawaitstart

 var start = async function(a, b) {

 }

관심있는 사람들을 위해 최상위 수준에 대한 제안 await은 현재 2 단계에 있습니다. https://github.com/tc39/proposal-top-level-await


1
불행히도 이것이 기본적으로 의미하는 것은 전체 코드베이스에 걸쳐 모든 함수를 비 동기화해야한다는 것입니다. await를 사용하려면 비동기 함수에서 수행해야합니다. 즉, 호출하는 함수에서 해당 함수의 응답을 기다려야합니다. 다시 말하면 모든 함수가 비 동기화되어야한다는 의미입니다. 나에게 이것은 await async가 사용할 준비가되지 않았 음을 의미합니다. 현재 함수가 동기식이든 비동기식이든 관계없이 await를 사용하여 비동기 메서드를 호출 할 수 있으면 프라임 타임에 대비할 수 있습니다.
Rodney P. Barbati

1
간접의 모든 단계를 통해 외부 처리해야의 결과에 의존하고, 모든 기능 을 에게서는 정의 할 async의 그 - 전체 지점async.
Gershom

현재 --experimental-repl-await옵션을 사용하여 node repl에서 사용할 수 있습니다 .
lodz

3

나는 동일한 문제가 있었고 다음 코드 블록이 동일한 오류 메시지를 표시했습니다.

repositories.forEach( repo => {
        const commits = await getCommits(repo);
        displayCommit(commits);
});

문제는 getCommits () 메소드가 비동기 였지만 Promise에 의해 생성 된 인수 저장소를 전달하고 있다는 것입니다. 그래서 다음과 같이 async라는 단어를 추가해야했습니다 : async (repo) 그리고 작동하기 시작했습니다.

repositories.forEach( async(repo) => {
        const commits = await getCommits(repo);
        displayCommit(commits);
});

0

async / await는 promise를 처리하는 메커니즘으로, 두 가지 방법으로 수행 할 수 있습니다.

functionWhichReturnsPromise()
            .then(result => {
                console.log(result);
            })
            .cathc(err => {
                console.log(result);

            });

또는 await를 사용하여 약속이 먼저 가득 채워질 때까지 기다릴 수 있습니다. 이는 거부되거나 해결되었음을 의미합니다.

이제 함수 내에서 await (Promise가 이행되기를 기다리는 중) 를 사용하려면 , 우리가 비동기 적으로 이행 할 약속을 기다리고 있기 때문에 컨테이너 함수는 반드시 비동기 함수 여야합니다 || 말이 맞습니까?.

async function getRecipesAw(){
            const IDs = await getIds; // returns promise
            const recipe = await getRecipe(IDs[2]); // returns promise
            return recipe; // returning a promise
        }

        getRecipesAw().then(result=>{
            console.log(result);
        }).catch(error=>{
            console.log(error);
        });

-2

"await는 비동기 함수에서만 유효합니다."

그런데 왜? 'await'는 명시 적으로 비동기 호출을 동기 호출로 전환하므로 호출자는 비동기 (또는 비동기)가 될 수 없습니다. 적어도 'await'에서 호출이 이루어지기 때문이 아닙니다.


1
실제로 await는 결과를 기다리지 않고 즉시 약속을 반환합니다. 이것이 바로 제가 전달하려고했던 것입니다. await가 실제로 기다렸다가 호출자에게 제어를 반환하지 않으면 await 키워드가 포함 된 함수는 말 그대로 비동기로 표시 될 수 없습니다. 그러나 그 대신 await를 포함하거나 결국 await를 포함하는 함수를 호출하는 함수를 호출하는 함수는 비동기 여야합니다. 기본적으로 await를 한 번만 호출하면 모든 함수가 비동기로 표시되어야합니다.
Rodney P. Barbati

-5

예, await / async는 훌륭한 개념 이었지만 구현은 완전히 망가졌습니다.

어떤 이유로 든 await 키워드는 비동기 메서드 내에서만 사용할 수 있도록 구현되었습니다. 이것은 사실 버그이지만, 바로 여기에서 그렇게 언급되는 것을 볼 수는 없습니다. 이 버그에 대한 수정 사항은 호출 함수 자체가 동기인지 비동기인지에 관계없이 비동기 함수를 호출하는 데만 사용할 수 있도록 await 키워드를 구현하는 것입니다.

이 버그로 인해 await를 사용하여 코드 어딘가에서 실제 비동기 함수를 호출하는 경우 모든 함수가 비동기로 표시되어야하며 모든 함수 호출이 await를 사용해야합니다.

이는 본질적으로 전체 애플리케이션의 모든 함수에 promise의 오버 헤드를 추가해야 함을 의미하며, 대부분은 비동기 적이 지 않으며 절대로 비동기 적이 지 않을 것입니다.

실제로 생각해 보면 함수에서 await를 사용하려면 await 키워드를 포함하는 함수가 ASYNC가 아니어야합니다. 이것은 await 키워드가 await 키워드가있는 함수에서 처리를 일시 중지하기 때문입니다. 해당 함수의 처리가 일시 중지되면 확실히 비동기가 아닙니다.

따라서 javascript 및 ECMAScript 개발자에게-다음과 같이 await / async 구현을 수정하십시오.

  • await는 비동기 함수를 호출하는 데만 사용할 수 있습니다.
  • await는 동기 또는 비동기 모든 종류의 함수에 나타날 수 있습니다.
  • 오류 메시지를 "await is only valid in async function"에서 "await can only be used to call async functions"로 변경합니다.

원하는 경우 버그라고 부를 수 있지만 동의하지 않습니다. "일시 중지"하는 코드는 없습니다. 오히려 외부 프로세스 (일반적으로 io)의 결과 없이는 완료 할 수없는 코드가 있습니다. 단일 스레드 인 자바 스크립트 VM과 달리 많은 외부 프로세스가 동시에 (비동기 적으로) 실행될 수 있어야하므로 이러한 코드를 "비동기"라고해야합니다. 리팩토링해야하는 함수가 많은 경우 많은 함수 async가 외부 프로세스의 결과를 필요로한다는 사실을 반영합니다. 그것은 제 생각에는 완전히 표준입니다.
Gershom

또한 await함수 호출에서만 사용할 수 있도록 제한하는 끔찍한 단점을 언급 할 가치가 있습니다. 단일 외부 프로세스의 경우 해당 프로세스가 완료되면 자바 스크립트 코드의 단일 지점 만 알림을받을 수 있습니다. 예를 들어 파일의 내용이 3 개의 독립적 인 목적을 위해 필요한 경우 각 목적은 독립적으로 수행해야합니다. let content = await readTheFile();이는 "파일 내용에 대한 약속"을 기다릴 수 없기 때문이며 "파일을 읽고 재개하는 행위"뿐입니다. 읽다".
Gershom

자, 멈추는 코드 나 완료 할 수없는 코드라고 부르지 말고 대기 차단은 어떻습니까? 여기에 문제가 있습니다. 대기가 차단되거나 완료 할 수없는 함수는 await 키워드를 포함하는 함수입니다. await 키워드로 호출되는 것은 비동기 함수가 아닙니다. 따라서 await 키워드를 포함하는 함수는 확실히 async로 표시 할 필요가 없습니다. 즉, 비동기식의 반대 인 대기 중 차단됩니다.
Rodney P. Barbati

이것을 완전히 명확하게하기 위해 다음을 고려하십시오. await는 비동기 함수를 동기식으로 보이게하여 비동기 함수의 사용을 단순화하기위한 것입니다 (즉, 특정 순서로 작업을 수행 할 수있게 함). await를 포함하는 함수를 비동기로 강제하는 것은 완전히 잘못된 이름입니다. await를 사용하여 동기가됩니다. await를 포함하는 함수는 모든 생각할 수있는 방식으로 절대적으로 비동기 함수가 아닙니다 !!!
Rodney P. Barbati

1
@ Gershom-합리적으로 들립니다. 감사!
Rodney P. Barbati
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.