TIL 1109 Promise async&await JSON.parse
Promise 객체
Promise.. 그것은 약속이다. 어떤약속이냐
웹에서
데이터를 얻어서 보내주거나
얻지 못한다면 (에러발생시) 이유와 함께
에러를 발생시키도록한 약속!
.then() 은 Promise 객체 내에서 resolve()에 전달된 데이터를 받는다.
.catch() 는 Promise 객체 내에서 에러 발생시 reject()에 전달된 데이터를 받는다.
Promise의 3가지 상태
- Pending (대기)
- Fulfilled (완료)
- Rejected (거부)
순서도
- pending
1-1 -resolve-> 2. fulfilled (settled)
1-2 -rejec-> 2. pending (settled)
Promise 객체는 이벤트 루프에서 대기상태를 유지하다가
실행순서가 되면 비동기적으로 실행되고
실행 중 오류가 발생하지 않으면 resolve()를 통해서 완료 상태(fulfilled)가 된다.
오류가 발생하면 reject()에 구현된 코드에 따라 오류 처리를 하게 된다.
JSON.parse
string 을 json 객체로 변환시켜주는 메서드.
fs.readFilej()이 파일 내용을 string 으로 가져오기 때문에
사용하기 위해 파일 내용을 json으로 변환시킬 때 사용.
const json = '{"result":true, "count":42}';
const obj = JSON.parse(json);
console.log(obj.count);
// expected output: 42
console.log(obj.result);
// expected output: true
Promise.resolve()
주어진 값으로 이행하는 Promise.then 객체를 반환합니다. 그 값이 프로미스인 경우, 해당 프로미스가 반환됩니다
resolve()로 값을 전달해주지 않으면 Promise의 state가 pending에서 변하지 않는다.
resolve()를 사용하고 종료된다면 state는 fulfilled 된다.
const promise1 = Promise.resolve(123);
//or
const promise1 = new Promise((resolve, reject) => {
resolve(123);
});
//then의 인자로 resolve의 인자(123)가 들어간다.
promise1.then((value) => {
console.log(value);
// expected output: 123
});
//아래처럼 배열도 인자로 사용가능.
var p = Promise.resolve([1,2,3]);
p.then(function(v) {
console.log(v[0]); // 1
});
파라미터가 1개일때 함수이름만 쓰면, 암묵적으로 함수의 매개변수로 전달 됨
getHen()
.then(getEgg)
.then(cook)
.then(console.log);
Promise.reject()
거부된 Promise 객체를 반환합니다.
아래처럼 에러가 발생한 경우 reject로 객체를 넘긴다.
const promise1 = new Promise((resolve, reject) => {
fs.readFile(filePath, 'utf8', (err, data)=>{
if(err) {
reject(err)
}else {
resolve(data)
}
});
});
promise1.then(value => console.log(value));
//에러 발생시 에러가 콘솔창에 찍힌다.
Promise.catch()
Promise 객체를 리턴하며, reject 된 케이스만 다룬다.
즉, 에러가 발생한 경우에만 호출된다.
const promise1 = new Promise((resolve, reject) => {
throw 'Uh-oh!';
});
promise1.catch((error) => {
console.error(error);
});
// expected output: Uh-oh!
.then()으로 체이닝하며 일련의 과정을 수행시켰을 경우,
수행 과정 중 에러가 발생했을 때
.catch()내부의 콜백함수가 실행되어서 에러핸들링을 하게 된다.
에러가 발생한 뒤의 .then()은 수행되지 않는다.
끝까지 에러가 발생하지 않으면 마지막 .then()까지 실행하고
.catch()는 실행하지 않는다.
Promise.finally()
.then()이나 .catch() 가 모두 호출되면 마지막에 반드시 호출된다.
promise
.then((value) => {
console.log(value);
})
.catch(error => {
console.log(error);
})
.finally(() => { // 성공하든 실패하든 마지막에 실행됨
console.log(`finally`);
})
Promise.all()
Promise 객체 배열을 인자로 받아서,
인자로 받은 Promise를 모두 병렬적으로 동시에 실행하고,
모든 Promise가 호출이 끝나기까지 기다렸다가 결과를 한번에 반환한다.
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
Promise.all([promise1, promise2, promise3]).then((values) => {
console.log(values);
});
// expected output: Array [3, 42, "foo"]
아래는 async function으로 병렬적으로 호출하는 방법 (Promise.all()을 쓰는게 더 좋다.)
function delay(ms){
return new Promise(resolve => setTimeout(resolve, ms));
}
async function getApple() {
await delay(1000);
return 'Apple';
}
async function getBanana() {
await delay(2000);
return 'Banana';
}
async function pickFruits() {
const applePromise = getApple();
const bananaPromise = getBanana();
const apple = await applePromise;
const banana = await bananaPromise;
return `${apple} + ${banana}`;
}
pickFruits().then(console.log);
//Promise 두개가 병렬적으로 실행되므로 3초 뒤가 아니라 2초 뒤에 'Apple + Banana'가 출력됨
//Promise.all 을 사용하면
function pickAllFruits() {
return Promise.all([getApple(), getBanana()])
.then(fruits => fruits.join(' + ')); //fruits === ['Apple', 'Banana']
}
pickAllFruits().then(console.log);
//병렬적으로 호출했을 때 가장 먼저 완료되는 Promise를 출력하기
function pickFastOne() {
return Promise.race([getApple(), getBanana()]);
}
pickFastOne().then(console.log);
//Banana보다 짧은 시간이 걸리는 Apple만 출력된다.
참고 : 드림코딩by엘리
async function ( async & await )
function에 async만 붙여주면 Promise 객체를 리턴하는 함수로 만들 수 있다! like Magic!
에러 처리는 try ~ catch 구문을 이용해야 한다
function resolveAfter2Seconds() {
return new Promise(resolve => {
setTimeout(() => {
resolve('resolved');
}, 2000);
});
}
async function asyncCall() {
console.log('calling');
try {
const result = await resolveAfter2Seconds();
} catch(error) {
console.log(error);
}
console.log(result);
// expected output: "resolved"
}
asyncCall();
await
await 키워드는 Promise를 기다리기 위해 사용됩니다.
async function 내부(코드블럭)에서만 사용할 수 있다.
Promise 객체를 리턴하는 함수는(async 키워드가 안붙어도)
모두 await로 완료를 기다리게 만들 수 있다.
function resolveAfter2Seconds(x) {
return new Promise(resolve => {
setTimeout(() => {
resolve(x);
}, 2000);
});
}
async function f1() {
var x = await resolveAfter2Seconds(10); //x 에는 resolve(x)로 리턴된 x 가 할당된다.
//Promise객체를 리턴하는 함수이므로 await로 비동기적으로 함수실행하고 종료는 동기적으로 기다리게 만들 수 있다.
console.log(x); // 10
//console.log(x)는 await를 기다렸다가 호출된다.
}
f1();
//10초 뒤에 10이 콘솔에 찍힘
아래는 await을 안쓴 경우와 쓴 경우
fetch('http://www.naver.com/data.json')
.then(response => response.json())
.then(json => {
console.log(json)
})
async function request() {
let response = await fetch('http://www.naver.com/data.json')
let json = await response.json()
console.log(json)
}
additional
- node.js 와 브라우저의 공통점 Promise 객체 사용가능.
- 브라우저에선 fs.readFile 못쓰고 node.js 에서 가능.
- node.js에는 fetch()가 없다. 3rd party 사용해야함.