ES2017 의 기능인 비동기 함수 는 약속 (특정 형식의 비동기 코드)과 await키워드 를 사용하여 비동기 코드를 동기화 된 모양으로 만듭니다 . 아래 코드 예제 에서 async / await 함수를 나타내는 키워드 async앞에있는 function키워드를 확인하십시오. await키워드는 사전을 고정하는 기능에없이 작동하지 않습니다 async키워드. 현재로서는 예외가 없으므로 최상위 레벨 대기가 작동하지 않습니다 (최상위 레벨은 함수 외부에서 대기를 의미합니다). 최상위에await 대한 제안 이 있지만 .
ES2017은 2017 년 6 월 27 일 JavaScript의 표준으로 비준 (즉 최종)되었습니다. Async await는 이미 브라우저에서 작동 할 수 있지만, 그렇지 않은 경우 babel 또는 traceur 와 같은 자바 스크립트 트랜스 파일러를 사용하여 기능을 계속 사용할 수 있습니다 . Chrome 55는 비동기 기능을 완벽하게 지원합니다. 따라서 최신 브라우저를 사용하는 경우 아래 코드를 사용해 볼 수 있습니다.
브라우저 호환성에 대해서는 kangax의 es2017 호환성 표 를 참조하십시오 .
다음은 async await 함수의 예입니다.이 함수 doAsync는 3 초의 일시 정지를 시작하고 각 일시 정지 후 시작 시간과의 시차를 인쇄합니다.
function timeoutPromise (time) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(Date.now());
}, time)
})
}
function doSomethingAsync () {
return timeoutPromise(1000);
}
async function doAsync () {
var start = Date.now(), time;
console.log(0);
time = await doSomethingAsync();
console.log(time - start);
time = await doSomethingAsync();
console.log(time - start);
time = await doSomethingAsync();
console.log(time - start);
}
doAsync();
await 키워드가 약속 값 앞에 놓이면 (이 경우 약속 값은 doSomethingAsync 함수에 의해 리턴 된 값임) await 키워드는 함수 호출의 실행을 일시 정지하지만 다른 함수는 일시 정지하지 않고 계속됩니다. 약속이 해결 될 때까지 다른 코드를 실행합니다. 약속이 해결 된 후에는 약속의 가치가 풀리며 대기 및 약속 표현이 현재 래핑되지 않은 값으로 대체되는 것으로 생각할 수 있습니다.
따라서 await는 대기를 일시 중지 한 다음 나머지 줄을 실행하기 전에 값을 줄 바꿈 해제하기 때문에 배열에서 기다리는 시간 차이를 수집하고 배열을 인쇄하는 아래 예제와 같이 for 루프 및 내부 함수 호출에서 사용할 수 있습니다.
function timeoutPromise (time) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(Date.now());
}, time)
})
}
function doSomethingAsync () {
return timeoutPromise(1000);
}
// this calls each promise returning function one after the other
async function doAsync () {
var response = [];
var start = Date.now();
// each index is a promise returning function
var promiseFuncs= [doSomethingAsync, doSomethingAsync, doSomethingAsync];
for(var i = 0; i < promiseFuncs.length; ++i) {
var promiseFunc = promiseFuncs[i];
response.push(await promiseFunc() - start);
console.log(response);
}
// do something with response which is an array of values that were from resolved promises.
return response
}
doAsync().then(function (response) {
console.log(response)
})
async 함수 자체는 약속을 반환하므로 위와 같이 또는 다른 async await 함수 내에서 체인을 사용하여 약속으로 사용할 수 있습니다.
위의 함수는 요청을 동시에 보내려면 다른 요청을 보내기 전에 각 응답을 기다릴 것 입니다. Promise.all 을 사용할 수 있습니다 .
// no change
function timeoutPromise (time) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(Date.now());
}, time)
})
}
// no change
function doSomethingAsync () {
return timeoutPromise(1000);
}
// this function calls the async promise returning functions all at around the same time
async function doAsync () {
var start = Date.now();
// we are now using promise all to await all promises to settle
var responses = await Promise.all([doSomethingAsync(), doSomethingAsync(), doSomethingAsync()]);
return responses.map(x=>x-start);
}
// no change
doAsync().then(function (response) {
console.log(response)
})
약속이 거부되면 시도 catch로 랩핑하거나 시도 catch를 건너 뛰고 오류가 async / await 함수 catch 호출로 전파되도록 할 수 있습니다. 특히 Node.js에서 약속 오류를 처리하지 않은 상태로 두지 않도록주의해야합니다. 다음은 오류의 작동 방식을 보여주는 몇 가지 예입니다.
function timeoutReject (time) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
reject(new Error("OOPS well you got an error at TIMESTAMP: " + Date.now()));
}, time)
})
}
function doErrorAsync () {
return timeoutReject(1000);
}
var log = (...args)=>console.log(...args);
var logErr = (...args)=>console.error(...args);
async function unpropogatedError () {
// promise is not awaited or returned so it does not propogate the error
doErrorAsync();
return "finished unpropogatedError successfully";
}
unpropogatedError().then(log).catch(logErr)
async function handledError () {
var start = Date.now();
try {
console.log((await doErrorAsync()) - start);
console.log("past error");
} catch (e) {
console.log("in catch we handled the error");
}
return "finished handledError successfully";
}
handledError().then(log).catch(logErr)
// example of how error propogates to chained catch method
async function propogatedError () {
var start = Date.now();
var time = await doErrorAsync() - start;
console.log(time - start);
return "finished propogatedError successfully";
}
// this is what prints propogatedError's error.
propogatedError().then(log).catch(logErr)
여기 로 가면 다가오는 ECMAScript 버전에 대한 완성 된 제안을 볼 수 있습니다.
ES2015 (ES6)에서만 사용할 수있는 대안은 발전기 기능을 래핑하는 특수 기능을 사용하는 것입니다. 생성기 함수에는 await 키워드를 주변 함수와 복제하는 데 사용할 수있는 yield 키워드가 있습니다. yield 키워드와 생성기 함수는 훨씬 더 일반적인 목적이며 async await 함수가 수행하는 것보다 더 많은 작업을 수행 할 수 있습니다. async await를 복제하는 데 사용할 수있는 생성기 함수 래퍼를 원한다면 co.js를 확인하십시오 . 그런데 비동기 대기 함수와 같은 co의 함수는 약속을 반환합니다. 솔직히이 시점에서 브라우저 호환성은 생성기 함수와 비동기 함수 모두에 대해 거의 동일하므로 비동기 대기 기능을 원한다면 co.js없이 비동기 함수를 사용해야합니다.
브라우저 지원은 실제로 IE를 제외한 모든 주요 현재 브라우저 (Chrome, Safari 및 Edge)의 비동기 기능 (2017 년 현재)에 매우 적합합니다.