JS 는 동기적인 언어. 런타임(자바스크립트가 구동하는 환경, 브라우저나 node.js)에서 JS 가 비동기적으로 작동하는 것을 도와줌.(이벤트 루프를 통해 작동함)
비동기를 동기로 바꿔주는 이유 : 예측, 제어가 가능한 코드를 작성하기 위해.
비동기 작업의 최종 완료 또는 실패를 나타내는 객체.
Promise 는 콜백함수를 함수에 전달하는 것이 아닌, 첨부된 콜백함수를 리턴하는 객체.
🔗 MDN - Promise
🔗 MDN - Using Promise
MDN 설명
Promise
는 프로미스가 생성된 시점에는 알려지지 않았을 수도 있는 값을 위한 대리자로, 비동기 연산이 종료된 이후에 결과 값과 실패 사유를 처리하기 위한 처리기를 연결할 수 있습니다. 프로미스를 사용하면 비동기 메서드에서 마치 동기 메서드처럼 값을 반환할 수 있습니다. 다만 최종 결과를 반환하는 것이 아니고, 미래의 어떤 시점에 결과를 제공하겠다는 '약속'(프로미스)을 반환합니다.
Promise
는 다음 중 하나의 상태(State)를 가집니다.
pending 중인 프로미스는 값과 함께 이행할 수도, 어떤 이유(오류)로 인해 거부될 수도 있습니다. 이행이나 거부될 때, 프로미스의 then
메서드에 의해 대기열(큐)에 추가된 처리기들이 호출됩니다. 이미 이행했거나 거부된 프로미스에 처리기를 연결해도 호출되므로, 비동기 연산과 처리기 연결 사이에 경합 조건은 없습니다.
Promise 생성 방법 : new Promise(func)
, Promise()
(주로 프로미스를 지원하지 않는 함수를 감쌀 때 사용)
new Promise가 반환하는 Promise 객체는 state, result 내부 프로퍼티를 갖습니다. 하지만 직접 접근할 수 없고 .then, .catch, .finally 의 메서드를 사용해야 접근이 가능합니다.
Promise
에는 세 가지의 상호독립적인 상태가 있습니다.(pending, fulfilled, rejected)
기본 상태는 pending(대기) 입니다. 비동기 처리를 수행할 콜백 함수(executor)가 성공적으로 작동했다면 fulfilled (이행)로 변경이 되고, 에러가 발생했다면 rejected (거부)가 됩니다.
pending 상태가 아니라면 settled 가 되었다고 부르지만(fullfilled 이거나 rejected 일 때), settled 는 상태가 아니라 언어적 편의일 뿐입니다.
resolve("전달값") 로 전달한 값은 해당 promise 안의 result 에 들어가게 됨.
.then 을 통해서 result 값을 가져올 수 있음.
.catch를 통해서 rejected -> error 값을 가져올 수 있음
Promise
실행 함수는 두 개의 파라미터를 가지고 있습니다.(resolved, unresolved)
Promise.resolve()
주어진 값으로 이행하는Promise
객체를 반환합니다. 이때 지정한 값이then
메서드를 가지는 값인 경우,Promise.resolve()
가 반환하는 프로미스는then
메서드를 "따라가서" 자신의 최종 상태를 결정합니다. 그 외의 경우, 반환된 프로미스는 주어진 값으로 이행합니다.어떤 값이 프로미스인지 아닌지 알 수 없는 경우, 보통 일일히 두 경우를 나눠서 처리하는 대신
Promise.resolve()
로 값을 감싸서 항상 프로미스가 되도록 만든 후 작업하는 것이 좋습니다.
Promise.reject(reason)
주어진 사유로 거부하는Promise
객체를 반환합니다.
- 그 외의 정적 메서드 :
Promise.all(iterable)
주어진 모든 프로미스가 이행하거나, 한 프로미스가 거부될 때까지 대기하는 새로운 프로미스를 반환합니다.
반환하는 프로미스가 이행한다면, 매개변수로 제공한 프로미스 각각의 이행 값을 모두 모아놓은 배열로 이행합니다. 배열 요소의 순서는 매개변수에 지정한 프로미스의 순서를 유지합니다.
반환하는 프로미스가 거부된다면, 매개변수의 프로미스 중 거부된 첫 프로미스의 사유를 그대로 사용합니다.
- 특징 : 배열로 인자를 전달해줘야 하고, 콜백함수의 인자에 결과값이 배열로 들어옵니다.
: 인자로 받는 배열의 Promise 중 하나라도 에러가 생기면 에러가 생기는 시점에 작동을 종료하고, 뒤의 코드를 실행하지 않습니다.(나머지 Promise 의 state 와 상관 없음)Promise.any(iterable)
주어진 모든 프로미스 중 하나라도 이행하는 순간, 즉시 그 프로미스의 값으로 이행하는 새로운 프로미스를 반환합니다.Promise.race(iterable)
주어진 모든 프로미스 중 하나라도 처리될 때까지 대기하는 프로미스를 반환합니다.
반환하는 프로미스가 이행한다면, 매개변수의 프로미스 중 첫 번째로 이행한 프로미스의 값으로 이행합니다.
반환하는 프로미스가 거부된다면, 매개변수의 프로미스 중 거부된 첫 프로미스의 사유를 그대로 사용합니다.
Promise.prototype.then()
, Promise.prototype.catch()
,Promise.prototype.finally()
메소드들은 Promise
를 반환하기 때문에 연결(Promise chaining)이 가능합니다.
then()
메서드는 Promise (en-US)를 리턴하고 두 개의 콜백 함수를 인수로 받습니다. 하나는 Promise가 이행했을 때, 다른 하나는 거부했을 때를 위한 콜백 함수입니다.
프로미스가 정상적으로 처리 되었을 경우 resolve 함수를 호출하고 .then 메서드로 접근할 수 있습니다. 또한 .then 안에서 리턴한 값이 Promise면 Promise의 내부 프로퍼티 result를 다음 .then 의 콜백 함수의 인자로 받아오고, Promise가 아니라면 리턴한 값을 .then 의 콜백 함수의 인자로 받아올 수 있습니다.
const promise1 = new Promise((resolve, reject) => { resolve('Success!'); }); promise1.then((value) => { console.log(value); // Expected output: "Success!" });
catch()
메서드는 Promise 가 rejected 되었을때 호출되는 Promise
객체의 메서드입니다. 즉시 동등한 Promise
객체를 리턴합니다.(Promise.prototype.then(undefined, onRejected)
의 축약버전입니다.)
프로미스에 reject 처리기 콜백을 추가하고, 콜백이 호출될 경우 그 반환값으로 이행하며 호출되지 않을 경우, 즉 이전 프로미스가 이행하는 경우 이행한 값을 그대로 사용해 이행하는 새로운 프로미스를 반환합니다.
finally()
메소드는 Promise
객체를 반환합니다. Promise가 처리되면 Promise의 resolved / rejected 여부에 관계없이 Promise
가 처리 된 후에 코드가 무조건 한 번은 실행됩니다.
프로미스의 이행과 거부 여부에 상관없이 처리될 경우 항상 호출되는 처리기 콜백을 추가하고, 이행한 값 그대로 이행하는 새로운 프로미스를 반환합니다.
function runInDelay(seconds){ return new Promise((resolve, reject) => { if(!seconds || seconds < 0){ reject(new Error('seconds 가 0보다 작음!')) } setTimeout(resolve, seconds * 1000) }) } runInDelay(1) .then(() => console.log('타이머 작동 완료!')) // 성공 시 필요한 일을 수행(resolve -> result 값을 가져올 수 있음) .catch(console.error) // 실패 시 에러를 처리. Promise 에서 catch 가 없으면 에러가 발생함.(reject -> error 값을 가져올 수 있음) .finally(() => console.log('끝!!')) // 성공/실패 상관없이 최종적으로 무조건 호출됨!
async
키워드 작성, async 함수 내에서만 await
키워드 작성.await
가 붙은 코드는 해당 코드의 동작이 끝나야만 다음 코드를 실행함.await
다음에 오는 함수는 프로미스 객체를 반환해야 함!await
키워드를 사용할 경우, 프로미스 객체의 내부 프로퍼티인 result
값을 바로 받아옴(then으로 안 꺼내도 됨)try...catch
문법async 함수는 항상 promise를 반환합니다. 만약 async 함수의 반환값이 명시적으로 promise가 아니라면 암묵적으로 promise로 감싸집니다.
- 사용법 :
// 함수 선언식 async function funcDeclarations() { await 작성하고자 하는 코드 ... } // 함수 표현식 const funcExpression = async function () { await 작성하고자 하는 코드 ... } // 화살표 함수 const ArrowFunc = async () => { await 작성하고자 하는 코드 ... }
❕ .bind
: 함수의 위치에 따라서 동적으로 변하는 this 의 값을 내가 원하는 값으로 고정하고 싶을 때 사용. 함수의 객체 this 값을 변경해줌.
bind의 두번째 인자에는 새로 복사한 함수에 전달하고 싶은 인자를 넣어줄 수 있음.
함수명.bind(null, 인자2) === null 을 넣어주면 똑같이 복사함.
🔗 참고 사이트 : https://joshua1988.github.io/web-development/javascript/js-async-await/
🔗 참고 사이트 : https://web.dev/promises/
요악하자면 Promise 객체는 비동기 처리때 사용되고 대기, 이행, 실패 처리 상태를 가지고 있다.
처리 성공시 resolve 를 수행해 이행 상태로 바꾸고 이러한 이행 상태의 처리 결과는 then( ) 으로 받는다.
반대로 처리 실패시 reject 를 수행해 실패 상태로 바꾸고 이 처리 결과는 catch( ) 로 받는다.