fetch는 url매개변수는 필수이고, 두번째 매개변수는 선택사항이다. option 에 아무것도 넘기지 않으면 요청은 GET 메서드로 진행된다.
fetch()를 호출하면 브라우저는 네트워크 요청을 보내고 promise가 반환된다.
1)url : 접근하고자 하는 url 2) [option] : 선택 매개변수(method, headers, body,mode,dredentials,cache 사용 가능)
.then((response) => reponse.json())
1. response(응답) 1단계 1) 서버에서 응답 헤더를 받자마자 fetch 호출 시 받은 promise 가 내장 클래스 Response의 인스턴스와 함께 이행 상태가된다. 이 단계는 아직 body가 서버에 도착하기 전이지만 개발자는 응답 헤더를 보고 요청이 성공적으로 처리되었는지 아닌지를 확인 할 수 있다. 네트워크 문제나 존재하지 않는 사이트에 접속 할 경우 같이 HTTP 요청을 보낼 수 없는 상태에서 프로미스는 거부 상태가 된다.
status : HTTP 상태 코드가 200과 299사이일 경우 true ok - boolean 값, HTTP 상태 코드가 200과 299 사이일 경우 true
2. response(응답) 2단계 = response.json() 추가 메서드를 호출해 응답 본문을 받는 단계
get이나 post로 불러온 응답 데이터를 JSON으로 파싱해줌
1) JSON 파싱 : json 형식의 문자열을 객체로 변환하는 것
2) 왜 객체로 변환시키는데 ? 서버와 데이터를 주고 받을때는 문자만 주고 받을 수 있다. array와 object 같은거 전송 불가능하다. JSON은 문자열이기 때문에 서버와 데이터 주고 받기가 가능함.
JSON을 그대로 받아와서 object로 안바꾸면 자스에서 객체 즉, 우리가 원하는 데이터를 끄집어낼수가 없음. 그래서 object로 변환을 시켜야함
- 콜백함수는 코드 분리를 못한다. 아래 방식이 최선이다. (결과를 받고 싶지 않아도 결괏값을 바로 받아야한다) 콜백헬
- setTimeoutPromise 라는게 가상으로 있다라고 치고, Promise 는 아래처럼 코드를 promise 변수에 담고 분리를 할 수가 있다. (결과를 나중에 받을 수 있다)
하지만, Promise.all 은 하나만 실패해도 나머지 다 실패처리해서 catch 로 가버리는 단점이있다. 따라서 성공한것도 다시 다 시도해야함. Promise.allSettled 는 성공한거 results 에 받고, 실패한것만 catch 로 간다.
즉비동기 처리에서 순차적 처리를 행하기 위해 사용되는 객체가 프로미스(Promise)이다.
- 1과 2가 먼저 출력되고, fetch API는 맨 마지막에 출력되는 것을 확인할 수 있다.(비동기처리)
🔸fetch API 는 Promise 데이터타입을 리턴한다. Promise 데이터 타입은 객체를 response한다.
- 아래 코드를 적어보면 콘솔창에 Promise 데이터 타입이 리턴된다.
let fetched = fetch('https://jsonplaceholder.typicode.com/comments');
console.log('fetched',fetched);
- 우리가 어떤 함수를 리턴할때, Promise가 리턴된다면 비동기적으로 동작할 가능성이 높다.
- 함수가 리턴한 값은 then과 catch라는 메소드를 사용할 수 있다.
- then과 catch는 콜백함수를 인자로 갖는다.
- then 의 파라미터는 result를 알려주고, catch의 파라미터는 reason을 알려준다.(물론 파라미터 명은 아무렇게나 쓸수있음)
- then은 fetch를 통해 실행한 결과가 성공했을때, then으로 전달된 콜백함수가 호출되도록 약속되어있다. 콜백함수가 호출되면서 결과값이 있다면 첫번째 파라미터로 받을 수 있다. Promise가 호출되는 fetch API가 실패를 한다면, catch안으로 전달된 콜백함수가 실행되고 이유를 알려준다.
- 비동기적인 작업을 처리할때, 그 작업이 성공했는지, 실패했는지 표준화된 방식을 이용해서 처리할수있도록 해준다.
- 성공했을때는 then, 실패했을때는 catch 메소드가 발동이 된다.
- response.json() 의 리턴값도 Promise로 나온다. 즉, response.json()메서드가 실행되고 나서, then을 호출할것이다 라는 뜻이다.
- 즉, fetch()를 쓰고나면 Promise가 리턴이 되는데, Promise가 리턴되는 곳은 뒤에 then, catch를 붙여서 Promise체이닝을 할 수가 있다.
🔸Promise 의 상태
- 생성된 직후의 프로미스는 기본적으로 pending 상태다. 이후 비동기 처리가 수행되면 비동기 처리 결과에 따라 다음과 같이 프로미스의 상태가 변경된다
3. Promise 만드는 방법
- Promise 생성자 함수를 new 연산자와 함께 호출하면 프로미스(Promise 객체)를 생성한다.
- Promise()를 생성하는 Producer 파트와, Promise를 사용하는 Consumer 파트로 나눌수있다. (이부분이 Promise 의 최대 장점이다. 코드 분리가 가능하다.)
- Promise() 에는 인자로 이 작업이 성공했는지, 실패했는지 알수있는 콜백함수가 들어가야한다.
- 콜백함수 안에는 2개의 파라미터가 들어간다 ( 성공했을때, 실패했을때 파라미터), 파라미터 명은 아무거나 써도 된다.
그런데 보통은 resolve, reject를 많이 쓴다.
- 그리고 중괄호 안에 resolve() 함수형태로 작성하면 then 이하의 코드가 실행이된다.
// 1. Producer : 프로듀서 만드는 파트
var 프로미스 = new Promise(function(resolve, reject){
resolve()
});
//2. Consumers : then,catch 로 프로듀서 사용하는 파트
프로미스.then(function(){
console.log('성공했을 때 출력되는 코드') //성공했을 때 출력되는 코드
}).catch(function(){
console.log('실패했을 때 출력되는 코드')
});
🔸setTimeout을 이용한 예제
- 비동기작업이 처리되고, 그 결과가 끝났을 때 Promise의 콜백으로 전달된 첫번째 파라미터에 담겨있는 함수를 호출하면, 작업이 끝났다라는 사실을 알려줄수있다.
let 프로미스 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('2초뒤에 실행하는 코드')
},2000)
})
프로미스.then((data)=>{
console.log('data',data) //data 2초뒤에 실행하는 코드
})
// 생성자 함수를 통해 프로토타입 메서드 사용
const resolvedPromise = new Promise((resolve) => resolve([1, 2, 3]));
resolvedPromise.then(console.log); // [1, 2, 3]
2️⃣Promise.all (잘 안씀)
- Promise.all 메서드는 여러 개의 비동기 처리를 모두 병렬처리할 때 사용한다.
= 인자로 전달된 프로미스들이 모두 완료될 때까지 기다린 후, 그 결과를 담은 배열을 반환하는 메서드
const requestData1 = () =>
new Promise((resolve) => setTimeout(() => resolve(1), 3000));
const requestData2 = () =>
new Promise((resolve) => setTimeout(() => resolve(2), 2000));
const requestData3 = () =>
new Promise((resolve) => setTimeout(() => resolve(3), 1000));
// 세 개의 비동기 처리를 순차적으로 처리
const res = [];
requestData1()
.then((data) => {
res.push(data);
return requestData2();
})
.then((data) => {
res.push(data);
return requestData3();
})
.then((data) => {
res.push(data);
console.log(res); // [1, 2, 3] ⇒ 약 6초 소요
})
.catch(console.error);
위 예제는 세 개의 비동기 처리를 순차적으로 처리한다.(then 메서드를 통해) 즉, 앞선 비동기 처리가 완료되면 다음 비동기 처리를 수행한다. 따라서 위 예제는 3 , 2 , 1 초를 다 더한 6초 이상이 소요된다. 따라서 이런 상황에서 Promise.all 메서드를 사용한다면 병렬적으로 처리할 수 있다.
Promise.all 메서드는 인수로 전달받은 배열의 모든 프로미스가 fulfilled 상태가 되면 종료한다. 따라서 Promise.all 메서드가 종료하는 데 걸리는 시간은 가장 늦게 fulfilled 상태가 되는 프로미스의 처리 시간보다 조금 더 길다. (3초보다 조금 더 소요된다.) 프로미스의 처리 시간에 의해 총 처리 시간이 결정되지만, 순서는 코드의 처리 순서를 보장한다. 첫 번째 프로미스가 가장 나중에 fulfilled 상태가 되어도 Promise.all 메서드는 첫 번째 프로미스가 resolve한 처리 결과부터 차례대로 배열에 저장해 그 배열을 resolve하는 새로운 프로미스를 반환한다. Promise.all 메서드는 모든 프로미스가 fulfilled 상태가 되면 모든 처리 결과를 배열에 저장해 새로운 프로미스를 반환하므로, 해당 처리중에 rejected가 발생될 경우 에러가 발생한다. fulfilled 상태가 되는 것을 기다리지 않고 즉시 종료한다
3️⃣Promise.race
- Promise.race 메서드는 Promise.all 메서드와 동일하게 프로미스를 요소로 갖는 배열 등의 이터러블을 인수로 전달받는다. - 하지만 Promise.race 메서드는 모든 프로미스가 fulfilled 상태가 되는 것을 기다리는 것이 아니라 가장 먼저 fulfilled 상태가 된 프로미스의 처리 결과를 resolve하는 새로운 프로미스를 반환한다.