비동기처리의 코드 진행 순서를 동기적으로 만들기 위해서 콜백함수를 사용했는데, 콜백함수 뒤에 콜백함수가 붙고 또 콜백함수가 붙는
콜백지옥
이 발생해서 생겨난 개념 Promise !!
약속해요 우리... 다시는 콜백지옥에 빠지지 말기로...
A promise is an object that may produce a single value some time in the future
자바스크립트 비동기 처리에 사용되는 객체!
현재에는 당장 얻을 수는 없지만 가까운 미래에는 얻을 수 있는 어떤 데이터에 접근하기 위한 방법을 제공합니다. 당장 얻을 수 없다라는 말은 데이터를 얻는데까지 지연(letency)이 발생하는 경우입니다. I/O나 Network를 통해서 데이터를 얻는 경우가 대표적인데, CPU에 의해서 실행되는 코드 입장에서는 엄청나게 긴 지연 시간으로 여겨지기 때문에 Non-blocking 코드를 지향하는 자바스크립트에서는 비동기 처리가 필수적입니다.
function findUser(id){
return new Promise((resolve) => {
setTimeout(function () {
console.log('0.1초기다림')
const user= {
id:id,
name:'USER'+id
}
resolve(user)
},100)
})
}
findUser(1).then(function(res) {
console.log('user:'+res)
})
//결과
// 0.1초기다림
// user: {id:1,name:USER1}
Promise
객체를 생성하여 리턴하는 findUser 함수.
findUser를 호출하여 그 리턴값을 .then
메서드를 사용하여 결과값을 가지고 실행할 로직을 넘겨줍니다.
💥 콜백함수와의 차이점은, 함수를 호출하면 Promise
타입의 결과값이 리턴되고, 이 결곽밧을 가지고 다음에 수행할 작업을 진행한다는 것입니다.
➡ 그래서 비동기 처리임에도 불구하고 동기처리처럼 직관적으로 코드를 읽을 수 있습니다.
Promise는 객체는 new
키워드와 생성자를 통해서 생성할 수 있는데 이 생성자는 함수를 인자로 받습니다. 그리고 이 함수 인자는 resolve
와 reject
라는 2개의 함수형 파라미터를 가집니다.
resolve()
: 미래 시점에 얻게될 결과를 넘겨주는 정상처리
reject()
: 미래 시점에 발생할 예외를 넘겨주는 예외처리
function devide(numA, numB) {
return new Promise((resolve, reject) => {
if (numB === 0) reject(new Error("Unable to devide by 0."))
else resolve(numA / numB)
})
}
devide(8, 2)
.then((result) => console.log("성공:", result))
.catch((error) => console.log("실패:", error))
//결과
// 성공: 4
devide(8, 0)
.then((result) => console.log("성공:", result))
.catch((error) => console.log("실패:", error))
//결과
// 실패: Error: Unable to devide by 0.
then()
: 정상적인 인자를 넘긴경우 호출됨
catch()
: 비정상적인 인자를 넘긴경우 호출됨
실제 개발을 할 땐, Promise를 직접 생성하기보다는 여러 라이브러리의 함수를 호출해서 리턴받은 promise를 then
,catch
를 통해 사용하는 경우가 더 많습니다.
⭐ RESTAPI를 호출할 때 사용하는 fetch()
브라우저 내장함수도 호출 결과를 Promise
객체로 리턴합니다. 저는
fetch("https://jsonplaceholder.typicode.com/posts/1")
.then((response) => console.log("response:", response))
.catch((error) => console.log("error:", error))
//결과
// response: Response {type: "cors", url: "https://jsonplaceholder.typicode.com/posts/1", redirected: false, status: 200, ok: true, …}
then()
, catch()
메서드는 또다른 Promise 객체를 리턴합니다. 그리고 이 Promise 객체는 인자로 넘긴 콜백함수의 리텃값을 다시 then
,catch
메서드를 통해 접근할 수 있습니다. 이처럼 연쇄적으로 계속 호출할 수 있습니다.. (어디서 본 거 같네요... 콜백함수...?)
fetch("https://jsonplaceholder.typicode.com/posts/1")
.then((response) => response.json())
.then((post) => post.userId)
.then((userId) => "https://jsonplaceholder.typicode.com/users/" + userId)
.then((url) => fetch(url))
.then((response) => response.json())
.then((user) => console.log("user:", user))
.catch((error) => console.log("error:", error))
//결과
// user: {id: 1, name: "Leanne Graham", username: "Bret", email: "Sincere@april.biz", address: {…}, …}
💥 then
,catch
의 인자로 넘긴 콜백함수는 3,4번째 줄 처럼 일반 객체를 리턴하든 또는 5번째 줄처럼 Promise
객체를 리턴하든 상관이 없다는 것을 주의해야합니다. 왜냐면 일반 객체를 리턴할 경우, then
,catch
메서도는 항상 그 객체를 얻을 수 있는 Promise 객체를 리턴하도록 되어있기 때문입니다!!
➡ 그런데 최근 메서드 체이닝 방식이 async/await
키워드로 대체되고 있습니다... 정말 자주 계속 바뀌네요.. 이래서 개발자가 되려면 끊임없이 공부해야한다고 하나봐요.. 무튼 해야겠죠? 다음 글에서 공부하고 정리할게요.