2017-12-13 13 views
13

가이드 및 튜토리얼을 async/await으로 읽으려고했지만 어디서나이 주소를 찾을 수없는 것 같습니다. 여기 이 JavaScript async/await 코드가 예상대로 작동하지 않는 이유는 무엇입니까?

문제의 코드입니다 : 우리는 볼

var func1 = new Promise((resolve, reject) => { 
 
     console.log("Func1"); 
 
     setTimeout(() => { 
 
     resolve(10); 
 
     }, 100); 
 
    }); 
 
    
 
    var func2 = new Promise((resolve, reject) => { 
 
     console.log("Func2"); 
 
     setTimeout(() => { 
 
     resolve(20); 
 
     }, 5000); 
 
    }) 
 
    
 
    let run = async() => { 
 
     let var1 = await func1; 
 
     let var2 = await func2; 
 
     console.log(var1); 
 
     console.log(var2); 
 
    } 
 

 
    run();

"FUNC1은"와 "이 Func2는"즉시 차례로 인쇄되는. 5 초 후 func2에 지정된 제한 시간이 지나면 "10"과 "20"이 인쇄됩니다. 여태까지는 그런대로 잘됐다.

그러나 나는이에 코드의 마지막 비트를 변경하는 경우 :

let run = async() => { 
    let var1 = await func1; 
    console.log(var1); 
    let var2 = await func2; 
    console.log(var2); 
} 

그런 다음 나는 console.log(var1)가 앞에 오는에도 불구하고, 즉시 인쇄 "FUNC1"하지만,뿐만 아니라 "이 Func2"을 참조하십시오. 100ms 후에 "10"이 오면 5 초 후 "20"이옵니다. MDN 가입일

:

식 비동기 기능 실행이 약속이 충족되거나 거부 될 때까지 정지하고, 이행 후 비동기 함수의 실행을 재개시킨다 기다린다.

하지만 이런 일은 일어나지 않는 것 같습니다. 그렇다면 "Func1", "10", func2가 실행되어 "Func2"가 인쇄되고 5 초 후에 "20"이 표시됩니다. func1이 실행되어야하며, 한번 해결되면 (100ms) console.log (var1)가 실행되어야합니다. 내가 여기서 무엇을 놓치고 있니?

+8

대기열을 만들 때 해결하기 시작합니다. –

+0

중복 가능성 있음 [동일한 async 기능/타이머 재설정에서 여러 setTimeout 사용 ] (https://stackoverflow.com/q/47751923/1048572) – Bergi

답변

7

이 이유는 이전에 약속 실행자를 이미 실행했기 때문입니다. Promise 생성자에 전달 될 때 약속 집행 멀리 똑바로 평가, 그래서 당신은 다음을받을 것이다 :

var func1 = new Promise((resolve, reject) => ...); // Logs "Func1" 
var func2 = new Promise((resolve, reject) => ...); // Logs "Func2" 

let run = async() => { 
    let var1 = await func1; 
    console.log(var1); // Logs 10 
    let var2 = await func2; 
    console.log(var2); // Logs 20 
} 

run(); 
2

가장 큰 문제는 여기 func1하고 func2이 기능하지 않습니다; 그것들은 약속입니다. Jonas W.와 마찬가지로 약속은 즉시 자신의 콜백 (resolve, reject) =>에 전화 할 것이고 기다리는 것은 그들이 해결 될 때까지 기다리게 할 것이라고 말합니다.

var func1 =() => { 
 
    return new Promise((resolve, reject) => { 
 
    console.log("Func1"); 
 
    setTimeout(() => { 
 
     resolve(10); 
 
    }, 100); 
 
    }); 
 
} 
 
     
 
var func2 =() => { 
 
    return new Promise((resolve, reject) => { 
 
    console.log("Func2"); 
 
    setTimeout(() => { 
 
     resolve(20); 
 
    }, 5000); 
 
    }); 
 
} 
 
     
 
let run = async() => { 
 
    let var1 = await func1(); 
 
    let var2 = await func2(); 
 
    console.log(var1); 
 
    console.log(var2); 
 
} 
 

 
run();

+1

"시작"에 대한 약속조차하지 않는 것이 좋습니다. * timeouts *는 즉시 시작되며, 약속은 나중에 생성됩니다 (나중에 해결됩니다). – Bergi

+0

@Bergi Promise로 전달되는 함수는 즉시 호출되어 해결하려고 시도합니다. Promise 클래스는 기본적으로 생성자에게 제공된 콜백을 시작하여 해결을 시작합니다. – FrankerZ

+0

예, promise * 생성자 *는 executor 콜백을 시작하고 promise의 결말로 끝나는 프로세스를 시작합니다 ('resolve'가 호출 될 때까지는 아무 것도 해결하지 못한다는 것을 알 수 있습니다). 그러나 많은 사람들은 약속 * 인스턴스 *가 여가 시간에 (또는 여러 번) 작업을 시작할 수 있다는 생각을하게됩니다. 이는 분명히 잘못되었습니다. – Bergi

0

await은 기본적으로 다음과 같은 값이을 계속하기 전에 사용할 수 있는지 enshure을 의미

당신은 여기에 원하는 결과를 볼 수 있습니다. 약속은 당신이 그것을 만들 때 해결되기 시작합니다, 그것이 언제 기다려야하는지는 중요하지 않습니다.

0

실행 기능은 동기화 된 순서로되어 있습니다. 코드는 단계별로 다음을 취합니다 :

  1. 회신이있을 때까지 기다리십시오.
  2. func2()를 호출하고 응답이있을 때까지 기다립니다.
  3. log var1.
  4. log var2.

그래서 마지막 2 단계는 func2() 호출이 약속을 완료 한 경우에만 실행됩니다. 타임 아웃 후의 데이터 따라서 var1과 var2를 로깅 할 때까지 5 초 동안 기다립니다.

다른 방법은 상당히 다릅니다 1. func1()을 호출하고 응답이있을 때까지 기다립니다. 2. var1을 기록하십시오. 3. func2()를 호출하고 응답이있을 때까지 기다립니다. 4. 로그 var2.

2 단계는 1 단계에서 데이터가 반환 될 때까지 대기합니다. 100ms 후 3 단계와 4 단계에서 동일하게 진행합니다.