동기적 통신 : 내가 하나의 데이터만 필요하더라도, 모~든 데이터가 동기적으로 통신되는 것
모든 데이터가 다시 들어오니까, 모든 화면을 브라우저가 다시 그려야한다.
비동기적 통신 : 필요한 데이터에 대해서만 JSON 파일로 주고받으며 서버와 통신한다.
= '문자화' 시켜준다.
비동기 통신 API
body를 직접 실어서 보내줘야지 실행할 수 있다.
확장프로그램 thunder를 다운받아서 get 주소에 넣고 send
const xhr = new XMLHttpRequest();
xhr.open('GET', END_POINT) //통신방식, 통신할 대상 , POST할때는 body를 함께 전달
ㄴ POST형식으로 받을 때는 body를 함께 전달해야한다.
XMLHttpRequest
import {} from './lib/index.js';
//xmlhttprequest
const xhr = new XMLHttpRequest();
xhr.open('GET', END_POINT) //통신방식, 통신할 대상
xhr.addEventListener('readystatechange', () => {
if(xhr.status >= 200 && xhr.status < 400){
console.log('통신 성공!');
}else {
console.log('통신 실패!');
}
})
xhr.send();
콜백함수
- parse -> json을 js객체로
- stringify() -> js객체를 json으로
- readtState ===4 : 데이터를 다 받았다는
function xhr(method, url) {
const xhr = new XMLHttpRequest();
xhr.open('GET', END_POINT) //통신방식, 통신할 대상 , POST할때는 body를 함께 전달
xhr.addEventListener('readystatechange', () => {
const {readyState, status, response} = xhr;
if(readyState === 4){
if(xhr.status >= 200 && xhr.status < 400){
console.log(xhr.response);
JSON.parse(response); //이걸 밖에 어떻게 끌어와서 쓸 수 있을까?
}else {
console.log('통신 실패!');
}
}
})
xhr.send(JSON.stringify());
}
xhr('GET, END_POINT')
JSON.parse를 밖에 꺼내와서 쓰고싶으면 어떻게 해야할까?
=> 콜백함수로 함수를 던져서, 성공 시 실행하도록한다.
function xhr(method, url, success) {
const xhr = new XMLHttpRequest();
xhr.open('GET', END_POINT) //통신방식, 통신할 대상 , POST할때는 body를 함께 전달
xhr.addEventListener('readystatechange', () => {
const {readyState, status, response} = xhr;
if(readyState === 4){
if(xhr.status >= 200 && xhr.status < 400){ //200은성공
console.log(xhr.response);
success(JSON.parse(response));//여기서 수행을 한다.
}else {
console.log('통신 실패!');
}
}
})
xhr.send(JSON.stringify());
}
xhr('GET, END_POINT',(data)=>{console.log(data)}) //함수를 세번쨰 인자로 넘긴다1
function xhr(obj) {
const {method = 'GET', url = '', onSuccess = null, onFail = null, body = null} = obj;
//구조분해할당 하면서 기본값까지 정의
const xhr = new XMLHttpRequest();
xhr.open(method, url) //통신방식, 통신할 대상 , POST할때는 body를 함께 전달
xhr.addEventListener('readystatechange', () => {
const {readyState, status, response} = xhr;
if(readyState === 4){
if(xhr.status >= 200 && xhr.status < 400){ //200은성공
console.log(xhr.response);
onSuccess(JSON.parse(response)); //여기서 수행을 한다.
}else {
onFail({message: '에러가 발생했습니다.'})
console.log('통신 실패!');
}
}
})
xhr.send(JSON.stringify(body));
}
// xhr('GET',
// END_POINT,
// (data)=>{console.log(data)},
// ({message})=> {console.log(message)},
// {name : 'tiger'}
// ); //인자가 너무 많아서 어렵다.
xhr({ //객체로 넘기면 편하다.
method:'POST',
url:END_POINT,
onSuccess(data){console.log(data)},
onFail(){ },
body:{name:'tiger'}
});
ㄴ 객체로 받기
post 방식
import {} from './lib/index.js';
//xmlhttprequest
function xhr({ //xhr 함수 정의 매개변수 / 본문
method = "GET",
url = "",
onSuccess = null,
onFail = null,
body = null,
headers = {
'Content-Type' : 'application/json',
'Access-Control-Allow-Origin' : '*' //모든 것을 받겠다. 는 뜻! 선택를 했더라도, 백엔드단에서 허용하지 않을 수 있다.
}
}){
const xhr = new XMLHttpRequest();
xhr.open(method, url) //통신방식, 통신할 대상 , POST할때는 body를 함께 전달
Object.entries(headers).forEach(([key, value])=>{
xhr.setRequestHeader(key,value);
})
xhr.setRequestHeader('Content-Type', 'application/json'); //header 를 정의 (개발자도구 > 네트워크 > users)
xhr.addEventListener('readystatechange', () => {
const {readyState, status, response} = xhr;
if(readyState === 4){
if(xhr.status >= 200 && xhr.status < 400){ //200은성공
console.log(xhr.response);
onSuccess(JSON.parse(response)); //여기서 수행을 한다.
}else {
onFail({message: '에러가 발생했습니다.'})
console.log('통신 실패!');
}
}
})
xhr.send(JSON.stringify(body));
}
xhr({ //객체로 넘기면 편하다.
method:'POST',
url:END_POINT,
onSuccess(data){console.log(data)},
onFail(){ },
body:{name:'tiger'}
});
자바스크립트 함수는 객체이다!
객체에서는 메서드를 정의해서 사용할 수 있다.
즉, xhr.get() / xhr.post() / xhr.delete() 와 같은 메서드의 형태로 비동기 통신을 정의하여 사용할 수가 있다.
ㄴ j.query를 쓰면 이미 정의된 메서드로도 사용 가능!
콜백 지옥
const first = getNode('.first');
const second = getNode('.second');
function delay(callback, timeout = 1000) {
setTimeout(callback, timeout)
}
delay(()=> {
first.style.top = ' -100px'
delay(()=> {
first.style.transform = 'rotate(360deg)'
delay(()=> {
first.style.top = '0';
second.style.top = '0';
})
second.style.transform = 'rotate(-360deg)'
})
second.style.top = ' 100px'
})
애니메이션을 차례로 처리해주고자 할 때 delay라는 함수를 계속해서 만들어줘야해서 콜백 지옥에 빠질 수 있다!
--> 이를 해결하기 위해서는 'promise' 가 필요하다!
promise
기본 형태
promise객체의 메서드
then, catch, finally
then
function delayP(){
return new Promise((resolve,reject)=>{
setTimeout(()=> {
resolve('성공~');
}, 3000);
})
}
const result = delayP();
result.then((res)=>{
console.log(res);
})
console.log();
promise 문 안에 setTimeout을 쓰는 이유는, 비동기 통신 환경과 동일하게 만들기 위해서 사용했다.
비어있는 promise 객체를 반환한다.
result를 불러온 다음에, 처리, 다음에, 처리
ㄴ 이러한 모습이 마치 콜백함수의 처리 방식과 동일하다!
catch
function delayP(){
return new Promise((resolve,reject)=>{
setTimeout(()=> {
// resolve('성공~');
reject('실패 ㅠㅠ');
}, 2000);
})
}
const result = delayP();
result
.then((res)=>{
console.log(res);
})
.catch((err)=>{
console.log(err);
})
promise가 reject된 경우에는 에러를 잡을 수 있다.
이 에러를 잡기 위해서 catch 메서드를 이용해서 err 객체를 보여줄 수 있다.
catch 절을 쓰지 않고도 에러를 잡을 수 있다 ?!!
=> then은 두번째 매개변수를 받을 수있는데 (첫번째 : 성공 / 두번째 : 실패)
function delayP(){
return new Promise((resolve,reject)=>{
setTimeout(()=> {
// resolve('성공~');
reject('실패 ㅠㅠ');
}, 2000);
})
}
const result = delayP();
result
.then((res)=>{
console.log(res);
},
(err)=> {
console.log(err);
}
)
Promise 를 이용하여 비동기 통신 진행하기!
ㄴ 훨씬 더 쉽게 해결해줄 수 있다.
function xhrPromise(method,url,body){
const xhr = new XMLHttpRequest();
xhr.open(method,url);
xhr.send(JSON.stringify(body));
return new Promise((resolve, reject) => {
xhr.addEventListener('readystatechange',()=>{
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 400){
resolve(JSON.parse(xhr.response)) //성공 시 resolve
}else{
reject() //실패 시 reject
// error
}
}
})
})
}
xhrPromise('GET',END_POINT)
.then((res)=> {
console.log(res);
})
.catch((err)=> {
err.message
})
await
1. promise 객체의 데이터를 받아온다.
2. promise 작업이 끝날 떄까지 아래 코드를 실행하지 않고 기다린다!
3. async 함수일 때에만 await을 사용할 수 있다.
async 함수는 항상 promise를 반환한다.