TIL - 6회차
2021.03.11
공부한 내용
- Promise API
- async/await
- JSON
Promise API
Promise
클래스에는 5가지 정적 메서드가 존재한다.
Promise.all
let promise = Promise.all([...promises...]);
Promise.all
은 요소 전체가 프라미스인 배열을 받고 새로운 프라미스를 반환한다.
배열 안에 프라미스들이 모두 처리되면 새로운 프라미스가 이행되는데, 배열 안 프라미스들의 결과값을 담은 배열이 새로운 프라미스의 result
가 된다.
const promise1 = Promise.resolve(1);
const promise2 = Promise.resolve(2);
const promise3 = Promise.resolve(3);
Promise.all([promise1, promise2, promise3]).then(values => {
console.log(values); // Array [1, 2, 3]
});
새로운 프라미스의 result
배열의 요소 순서는 Promise.all
에 전달되는 프라미스 순서와 상응한다.
첫 번째 프라미스가 가장 늦게 이행되더라도 처리 결과는 배열의 첫 번째 요소에 저장된다.
실사용 예시 모던자바스크립트 사이트에서 가져왔습니다.
let names = ['iliakan', 'remy', 'jeresig'];
let requests = names.map(name => fetch(`https://api.github.com/users/${name}`));
Promise.all(requests)
.then(responses => {
// 모든 응답이 성공적으로 이행되었습니다.
for(let response of responses) {
alert(`${response.url}: ${response.status}`); // 모든 url의 응답코드가 200입니다.
}
return responses;
})
// 응답 메시지가 담긴 배열을 response.json()로 매핑해, 내용을 읽습니다.
.then(responses => Promise.all(responses.map(r => r.json())))
// JSON 형태의 응답 메시지는 파싱 되어 배열 'users'에 저장됩니다.
.then(users => users.forEach(user => alert(user.name)));
기타 정보!
Promise.all
에 전달되는 프라미스 중 하나라도 거부되면,Promise.all
이 반환하는 프라미스는 에러와 함께 거부된다.
하나라도 거부되면 배열에 저장된 다른 프라미스의 결과도 잊혀진다 이행된 결과도 무시된다.- 배열의 모든 요소가 Promise 인스턴스일 필요는 없다.
프라미스가 아닌 객체가 배열로 들어가면, 요소가 그대로 결과 배열로 전달된다.
Promise.allSettled
최근에 추가된 문법!! -> 구식 브라우저를 위한 폴리필 필요
Promise.all
같은 경우 프라미스가 하나라도 거절되면 전체가 거절되지만 Promise.allSettled
은 여러 요청 중 하나가 실패해도 다른 요청의 결과는 여전히 존재해야하는 상황에서 사용할 수 있다.
Promise.allSettled
에서 반환되는 배열
- 응답이 성공할 경우 =>
{status:"fulfilled", value:result}
- 에러가 발생한 경우 =>
{status:"rejected", reason:error}
예제 모던자바스크립트 사이트에서 가져왔습니다.
let urls = [
'https://api.github.com/users/iliakan',
'https://api.github.com/users/remy',
'https://no-such-url'
];
Promise.allSettled(urls.map(url => fetch(url)))
.then(results => {
results.forEach((result, num) => {
if (result.status == "fulfilled") {
alert(`${urls[num]}: ${result.value.status}`);
}
if (result.status == "rejected") {
alert(`${urls[num]}: ${result.reason}`);
}
});
});
//result
[
{status: 'fulfilled', value: ...응답...},
{status: 'fulfilled', value: ...응답...},
{status: 'rejected', reason: ...에러 객체...}
]
Promise.race
Promise.race
는 Promise.all
과 비슷하다.
하지만 Promise.race
는 가장 머저 처리되는 프라미스의 결과를 반환한다.
Promise.race([
new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)),
new Promise((resolve, reject) => setTimeout(() => reject(new Error("에러 발생!")), 2000)),
new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000))
]).then(alert); // 1
첫 번째 프라미스가 가장 빨리 처리상태가 되기 때문에 첫 번째 프라미스의 결과인 1이 반환된다. 가장 빨리 처리된 프라미스가 나타난 순간 다른 프라미스의 결과 또는 에러는 무시된다.
Promise.resolve/reject
Promise.resolve
,Promise.reject
는async/await
문법이 생긴 후 근래에는 거의 사용하지 않음
Promise.resolve
Promise.resolve(value)
는 결과값이 value
인 성공 상태의 프라미스를 생성한다.
let promise = new Promise(resolve => resolve(value));
Promise.resolve
는 호환성을 위해 함수가 프라미스를 반환하도록 해야 할 때 사용한다.
함수의 반환값(return값)으로
Promise.resolve()
를 사용하면 그 함수를 호출하면 프라미스가 반환된다는 것이 보장되기 때문에
function().then(..)
을 사용할 수 있다.function A(value) { if(value) return Promise.resolve(value); } A(value).then(....);
Promise.reject
Promise.reject(error)
는 결과값이error
인 거부 상태 프라미스를 생성한다.let promise = new Promise((resolve, reject) => reject(error));
Async/Await
ES2017에 새롭게 등장한 자바스크립트 비동기 처리 문법
async function 함수명() {
await 비동기_처리_메서드_명();
}
비동기 처리 메서드가 꼭 프로미스 객체를 반환해야 await
가 의도한 대로 동작한다. 일반적으로 await
의 대상이 되는 비동기 처리 코드는 Axios등 프라미스를 반환하는 API 호출 함수이다.
async/await란 무엇인가?
ES2017에 새롭게 등장한 자바스크립트 비동기 처리 문법
async function 함수명() {
await 비동기_처리_메서드_명();
}
비동기 처리 메서드가 꼭 프로미스 객체를 반환해야 await
가 의도한 대로 동작한다. 일반적으로 await
의 대상이 되는 비동기 처리 코드는 Axios등 프라미스를 반환하는 API 호출 함수이다.
Promise
를 기반으로 사용되는 비동기 코드를 좀 더 동기적인 코드처럼 작성할 수 있게 해주는 문법이다. 기존의 비동기 처리 방식인 콜백 함수와 프라미스의 단점을 보완해준다.
async/ await
은Promise
를 대체하는 것이 아니라는 것을 유념해야 한다.
Promise
를 사용하지만then
,catch
메서드를 사용하여 컨트롤 하는 것이 아닌 동기적 코드처럼 반환 값을 변수에 할당하여 작성할 수 있게끔 도와주는 문법이다.
async 함수
async
는 function앞에 위치한다.
async function f() {
return 1;
}
function앞에 async
키워드를 붙이면 그 함수는 항상 프라미스를 반환한다. 프라미스가 아닌 값을 반환하더라도 성공(resolve) 상태의 프라미스로 값을 감싼 성공 프라미스가 반환되도록 한다.
즉, async
가 붙은 함수는 반드시 프라미스를 반환하고, 프라미스가 아닌 것은 프라미스로 감싸서 반환한다.
반드시
Promise
를 반환하므로.then
,.catch
메서드 사용 가능
await
await
는 async
함수 안에서만 동작한다.
// await는 async 함수 안에서만 동작합니다.
let value = await promise;
자바스크립트는 await
키워드를 만나면 프라미스가 처리(Settled)상태가 될 때까지 기다린다. 결과는 그 이후에 반환!!
async function f() {
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve("완료!"), 1000)
});
let result = await promise; // 프라미스가 이행될 때까지 기다림
alert(result); // "완료!"
}
f();
이렇게 함수를 호출하면 await
구문에서 Promise
가 처리될 때까지 실행이 잠시 중단되었다가 프라미스가 처리 완료되면 실행이 재개된다. ->1초 뒤에 "완료!"가 출력된다.
await
는 말 그대로 프라미스가 처리될 때까지 함수 실행을 기다리게 만든다. 프라미스가 처리되면 그 결과와 함께 실행이 재개된다. 프라미스가 처리되길 기다리는 동안엔 엔진이 다른 일(다른 스크립트를 실행, 이벤트 처리 등)을 할 수 있기 때문에, CPU 리소스가 낭비되지 않는다.
await
키워드는async
함수에서만 사용 가능하며 일반 함수에는 사용할 수 없다.
async
함수가 아닌 곳에서 사용하면SyntaxError
가 발생된다.
async/await 실사용 예제
function fetchUser() {
var url = 'https://jsonplaceholder.typicode.com/users/1'
return fetch(url).then(function(response) {
return response.json();
});
}
function fetchTodo() {
var url = 'https://jsonplaceholder.typicode.com/todos/1';
return fetch(url).then(function(response) {
return response.json();
});
}
//async 함수
async function logTodoTitle() {
var user = await fetchUser();
if (user.id === 1) {
var todo = await fetchTodo();
console.log(todo.title);
}
}
이렇게 여러 개의 비동기 처리 코드를 다룰 때 async/await
문법을 많이 사용한다. 콜백이나 프라미스보다 훨씬 더 깔끔하게 코드를 작성할 수 있다.
async 클래스 메서드
메서드 앞에 async
키워드를 추가하면 async
클래스 메서드를 선언할 수 있다.
class Waiter {
async wait() {
return await Promise.resolve(1);
}
}
new Waiter()
.wait()
.then(alert); // 1
async
메서드와async
함수는 프라미스를 반환하고await
를 사용할 수 있다는 공통점이 있다.
에러 핸들링
프라미스가 정상적으로 이행되면 await promise
는 프라미스 객체의 result
에 저장된 값을 반환한다. 반면 프라미스가 거부되면 마치 throw
문을 작성한 것처럼 에러가 던져진다.
async function f() {
await Promise.reject(new Error("에러 발생!"));
}
//같은 코드
async function f() {
throw new Error("에러 발생!");
}
async/await
에서 예외 처리 방법은 try...catch
를 사용한다.
async function logTodoTitle() {
try {
var user = await fetchUser();
if (user.id === 1) {
var todo = await fetchTodo();
console.log(todo.title);
}
} catch (error) {
console.log(error);
}
}
- 위 코드처럼
async
에서는catch{}
를 사용하면 된다. 에러가 발생하면 제어 흐름이catch{}
블록으로 넘어간다.- 여러 줄의 코드를
try
로 감싸는 것도 가능하다.- 네트워크 통신 오류뿐만 아니라 간단한 타입 오류 등 일반적인 에러까지도
catch
로 잡아낼 수 있다.- 에러는
error
객체에 담겨 발생한 에러의 유형에 맞게 에러 코드를 처리해 준다.
try...catch
가 없으면 async
함수에 .catch()
를 추가해서 처리해 준다.
async function f() {
let response = await fetch('http://유효하지-않은-url');
}
// f()는 거부 상태의 프라미스가 됩니다.
f().catch(alert); // TypeError: failed to fetch
기타
console.log(0);
function promise() {
console.log(1);
return new Promise(resolve => {
setTimeout(() => {
console.log(2);
resolve('resolved');
}, 2000);
});
}
console.log(3);
async function asyncCall() {
try {
console.log(4);
const result = await promise(); // Promise가 settled될 때까지 기다린 후 resolve된 값을 할당한다.
console.log(result);
console.log(5);
} catch(err) {
console.error(err); // error 발생 시 catch 블락에서 잡히도록 handling
}
}
console.log(6);
asyncCall();
// 출력 값
0
3
6
4 // asyncCall 호출
1 // promise 함수 호출
2 // 2초 후 setTimeout 콜백 함수 호출
resolved // resolve함수 호출
5 // await 후 다음 코드 실행
비동기 상황에서는 어떤 이벤트가 먼저 완료될 지 순서를 정확하게 알 수 없지만 async/await
문법을 사용하면 먼저 완료되어야 하는 이벤트들의 순서대로 (동기적으로 실행되는) 코드를 작성할 수 있다.
위 코드에서 console.log의 출력 순서를 보면 알 수 있다.
실제 코드를 작성할 때에는
axios
나fetch
를 통해ajax
요청하면 자동으로Promise
를 반환해주기 때문에Promise
객체를 직접 생성하는 경우보다Promise
로 반환되는 객체들에async/await
을 사용하여 비동기 처리하는 경우가 대부분이다.
JSON
JSON (JavaScript Object Notation)
JavaScript Object Notation
라는 의미의 축약어로 데이터를 저장하거나 전송할 때 많이 사용되는경량의 DATA - 교환 형식
이다.Javascript
에서 객체를 만들 때 사용하는 표현식을 의미한다.JSON
표현식은 사람과 기계 모두 이해하기 쉬우며 용량이 작아서, 최근에는JSON
이XML
을 대체해서 데이터 전송 등에 많이 사용된다.JSON
은 데이터 포맷일 뿐이며 어떠한 통신 방법도, 프로그래밍 문법도 아닌 단순히 데이터를 표시하는 표현 방법일 뿐이다.- 주로 클라이언트(web)와 서버 간에 데이터를 전송 하는데 사용된다.
- 파일의 확장자는 .json 이다.
JSON
인터넷 미디어 타입은 application/json 이다.
특징
- 서버와 클라이언트 간의 교류에서 일반적으로 많이 사용된다.
- 자바스크립트 객체 표기법과 아주 유사하다.
- 자바스크립트를 이용하여
JSON
형식의 문서를 쉽게 자바스크립트 객체로 변환할 수 있는 이점이 있다. JSON
문서 형식은 자바스크립트 객체의 형식을 기반으로 만들어졌다.- 자바스크립트의 문법과 굉장히 유사하지만 텍스트 형식일 뿐이다.
- 다른 프로그래밍 언어를 이용해서도 쉽게 만들 수 있다.
- 특정 언어에 종속되지 않으며, 대부분의 프로그래밍 언어에서
JSON
포맷의 데이터를 핸들링 할 수 있는 라이브러리를 제공한다. JSON
을 지원하는 함수들은 언어마다 존재한다.
문법
JSON
형식은 자바스크립트 객체와 마찬가지로key / value
가 존재할 수 있으며key
값이나 문자열은 항상 쌍따옴표를 이용하여 표기해야한다.- 객체, 배열 등의 표기를 사용할 수 있다.
- 일반 자바스크립트의 객체처럼 원하는 만큼 중첩시켜서 사용할 수도 있다.(쉼표
,
로 나열) JSON
형식에서는null
,number
,string
,array
,object
,boolean
을 사용할 수 있다.
형식
name - value
: 이름과 값의 쌍으로 이루어진다.
{
"Name": "haha",
"age": 20,
"email": "[email protected]"
}
- 리스트 형식 (배열[Array], 객체{Object} 사용 가능)
{
"animal" : {
"dog" : [
{"name":"nana", "age":1},
{"name":"jo", "age":2},
{"name":"tia", "age":3}
],
"cat" : [
{"name":"haha", "age":4},
{"name":"nabi", "age":5},
{"name":"saho", "age":6}
]
}
}
메서드
- JSON.parse( json ) : JSON 형식의 텍스트를 자바스크립트 객체로 변환한다.
- JSON.stringify( object ) : 자바스크립트 객체를 JSON 텍스트로 변환한다.
Author And Source
이 문제에 관하여(TIL - 6회차), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@wdh008/TIL-6회차저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)