-
Promise & Async, Await개발/Javascript 2022. 6. 6. 10:39
*복습 자료라서 뻔한 내용은 생략
Summary.
1. A Promise is an object representing the eventual completion or failure of an asynchronous operation
2. A Promise is a proxy for a value not necessarily known when the promise is created
+ instead of immediately returning the final value, the asynchronous method returns a promise to supply the value at some point in the future
+ 3가지 state: pending, fulfilled, rejected
+ When either of these options happens, the associated handlers queued up by a promise's then method are called.
+ then(), catch() 함수 둘 다 Promise를 return 하므로 Chaining 가능
+ then() 함수에 Promise 반환하는 callback 함수가 없으면 다음 Chain으로 넘어감 -> 따라서 catch() 함수를 마지막에만 둬도 동작함. 만약 즉시 처리가 필요하면 then() 함수의 두번째 인자로 넣어두면 됨
3. 즉, Promise 생성 시 이미 async 함수는 실행되고, 결과가 settled (resolved or rejected) 됐을 때는 queued up 된 handler가 바로 실행됨
+ then() 함수로 handler 등록시키는데, 그 전에 settled 돼있을 수도 있고 안돼있을 수도 있음. queue 이므로
4. Static Method인 Promise.resolve() 와 Promise.reject() 는 주어진 값과 함께 Promise를 return 하는 함수
+ 아래와 같은 방식으로 Promise 정의 및 생성함 (setTimeout 대신 다른 async function을 수행하는 식)
+ resolve, reject 를 인수로 갖는 function 정의해서 new Promise(Foo) 처럼 Promise 생성하고, then으로 이어서 동작시키면 됨)
let myFirstPromise = new Promise((resolve, reject) => { // We call resolve(...) when what we were doing asynchronously was successful, and reject(...) when it failed. // In this example, we use setTimeout(...) to simulate async code. // In reality, you will probably be using something like XHR or an HTML5 API. setTimeout( function() { resolve("Success!") // Yay! Everything went well! }, 250) }) myFirstPromise.then((successMessage) => { // successMessage is whatever we passed in the resolve(...) function above. // It doesn't have to be a string, but if it is only a succeed message, it probably will be. console.log("Yay! " + successMessage) });
5. Promise 인스턴스 함수인 then, catch는 Promise Constructor에 넘겨주는 함수와는 다르게 동작함
+ then/catch는 항상 Promise를 return 함
+ 값을 return 할 경우, Promise의 값을 해당 값으로 설정해줌 (return 안할 경우 undefined로 설정됨)
+ 만약 callback handler 이 주어지지 않으면 그냥 다음으로 넘어감
+ 다음이 then() 함수 syntax
p.then(onFulfilled[, onRejected]); p.then(value => { // fulfillment }, reason => { // rejection });
6. Promise Chain을 더 깔끔하게 작성하기 위해 나온 키워드가 Async, Await (ECMAScript 2017)
+ Await은 Async 함수 내에서만 사용 가능
+ Async Function Declaration 과 Expression 둘 다 가능
+ Async Function도 Promise 반환 (즉, 이 함수 자체도 Await 대상일 수 있음. 실제로 그렇게 다룰 듯. 물론 후속처리할 것 없으면 await 안해도 됨)
function foo() { return Promise.resolve(1) } // same as above async function foo() { return 1 }
7. Promise.all, Promise.allSettled, Promise.any 처럼 Parallel 한 실행법도 있음 (Composition)
+ reduce 함수 이용도 가능 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises#composition
8. Promise callbacks are handled as a Microtask whereas setTimeout() callbacks are handled as Task queues.
const wait = ms => new Promise(resolve => setTimeout(resolve, ms)); wait(0).then(() => console.log(4)); Promise.resolve().then(() => console.log(2)).then(() => console.log(3)); console.log(1); // 1, 2, 3, 4
9. Callback Hell -> Promise -> Async/Await 변화
doSomething(function(result) { doSomethingElse(result, function(newResult) { doThirdThing(newResult, function(finalResult) { console.log('Got the final result: ' + finalResult); }, failureCallback); }, failureCallback); }, failureCallback);
doSomething() .then(function(result) { return doSomethingElse(result); }) .then(function(newResult) { return doThirdThing(newResult); }) .then(function(finalResult) { console.log('Got the final result: ' + finalResult); }) .catch(failureCallback); // catch(failureCallback) 은 then(null, failureCallback)과 같음 (원래 then(successFunc, failFunc))
doSomething() .then(result => doSomethingElse(result)) .then(newResult => doThirdThing(newResult)) .then(finalResult => { console.log(`Got the final result: ${finalResult}`); }) .catch(failureCallback);
try { const result = syncDoSomething(); const newResult = syncDoSomethingElse(result); const finalResult = syncDoThirdThing(newResult); console.log(`Got the final result: ${finalResult}`); } catch(error) { failureCallback(error); }
// ECMAScript 2017 async function foo() { try { const result = await doSomething(); const newResult = await doSomethingElse(result); const finalResult = await doThirdThing(newResult); console.log(`Got the final result: ${finalResult}`); } catch(error) { failureCallback(error); } }
Additional.
1. incumbent realm tracking 란?
2. unhandledrejection은 reject 발생 시 자동으로 global (ex) window or Worker)로 전달되는 RejectionEvent
ex) node.js - process.on("unhandledRejection", function(reason, promise){});
3. Nesting 잘 활용하면 Error 세심하게 관리 가능
+ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises#nesting
doSomethingCritical() .then(result => doSomethingOptional(result) .then(optionalResult => doSomethingExtraNice(optionalResult)) .catch(e => {})) // Ignore if optional stuff fails; proceed. .then(() => moreCriticalStuff()) .catch(e => console.error("Critical failure: " + e.message));
Reference.
'개발 > Javascript' 카테고리의 다른 글
History (ECMAScript) (0) 2022.06.06 Runtime / Execution Stack / Task Queue (0) 2022.06.06 Module System (0) 2022.06.05 Prototype Chain (0) 2022.06.05 Memory Management (0) 2022.06.05