JSONPlaceholder를 이용하여 배워보자!
브라우저 검사 - network 창을 통해서 확인!
const xhr = new XMLHttpRequest(); // 이 객체를 통해 HTTP 요청을 보낼 수 있게 됨. 브라우저에 내장
// 이 자체로는 네트워크 활동이 안됨. - 요청 구성
xhr.open("GET", "https://jsonplaceholder.typicode.com/posts");
// 요청 전송
xhr.send();
[
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
},
{
"userId": 1,
"id": 2,
"title": "qui est esse",
"body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
}
]
"를 사용해야한다.const xhr = new XMLHttpRequest(); // 이 객체를 통해 HTTP 요청을 보낼 수 있게 됨. 브라우저에 내장
xhr.open("GET", "https://jsonplaceholder.typicode.com/posts"); // 이 자체로는 네트워크 활동이 안됨. - 요청 구성
xhr.onload = function () {
console.log(xhr.response);
const listOfPosts = JSON.parse(xhr.response);
console.log(listOfPosts);
};
xhr.send(); // 요청 전송
JSON.stringify() : JavaScript 코드나 객체, 배열을 JSON 데이터로 변환해준다.JSON.parse() : JSON 데이터를 JavaScript로 변환해준다.const xhr = new XMLHttpRequest(); // 이 객체를 통해 HTTP 요청을 보낼 수 있게 됨. 브라우저에 내장
xhr.open("GET", "https://jsonplaceholder.typicode.com/posts"); // 이 자체로는 네트워크 활동이 안됨. - 요청 구성
xhr.responseType = "json"; // 자동으로 구문 분석이 된다.
xhr.onload = function () {
const listOfPosts = xhr.response;
console.log(listOfPosts);
};
xhr.send(); // 요청 전송
JSONPlaceholder에서 받아온 데이터 뿌려주기
const listElement = document.querySelector(".posts");
const postTemplate = document.getElementById("single-post");
const xhr = new XMLHttpRequest(); // 이 객체를 통해 HTTP 요청을 보낼 수 있게 됨. 브라우저에 내장
xhr.open("GET", "https://jsonplaceholder.typicode.com/posts"); // 이 자체로는 네트워크 활동이 안됨. - 요청 구성
xhr.responseType = "json"; // 자동으로 구문 분석이 된다.
xhr.onload = function () {
console.log(xhr.response);
// const listOfPosts = JSON.parse(xhr.response);
const listOfPosts = xhr.response;
console.log(listOfPosts);
for (const post of listOfPosts) {
const postEl = document.importNode(postTemplate.content, true); // true = deep clone
postEl.querySelector("h2").textContent = post.title.toUpperCase();
postEl.querySelector("p").textContent = post.body;
listElement.append(postEl);
}
};
xhr.send(); // 요청 전송
const listElement = document.querySelector(".posts");
const postTemplate = document.getElementById("single-post");
function sendHttpRequest(method, url) {
const promise = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.responseType = "json";
xhr.onload = function () {
resolve(xhr.response);
};
xhr.send(); // 요청 전송
});
return promise;
}
async function fetchPost() {
const responseData = await sendHttpRequest(
"GET",
"https://jsonplaceholder.typicode.com/posts"
);
const listOfPosts = responseData;
for (const post of listOfPosts) {
const postEl = document.importNode(postTemplate.content, true);
postEl.querySelector("h2").textContent = post.title.toUpperCase();
postEl.querySelector("p").textContent = post.body;
listElement.append(postEl);
}
}
fetchPost();
function sendHttpRequest(method, url, data) {
const promise = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.responseType = "json";
xhr.onload = function () {
resolve(xhr.response);
};
xhr.send(JSON.stringify(data)); // 요청 전송
});
return promise;
}
async function createPost(title, content) {
const userId = Math.random();
const post = {
title: title,
body: content,
userId: userId,
};
sendHttpRequest("POST", "https://jsonplaceholder.typicode.com/posts", post); // 서버에 데이터를 생성하려는 POST 요청의 경우 생성하고자하는 데이터를 나가는 요청에 추가해야한다.
}
createPost("DUMMY", "A dummy post!");
const listElement = document.querySelector(".posts");
const postTemplate = document.getElementById("single-post");
const form = document.querySelector("#new-post form");
const fetchButton = document.querySelector("#available-posts button");
function sendHttpRequest(method, url, data) {
const promise = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.responseType = "json";
xhr.onload = function () {
resolve(xhr.response);
};
xhr.send(JSON.stringify(data)); // 요청 전송
});
return promise;
}
async function fetchPost() {
const responseData = await sendHttpRequest(
"GET",
"https://jsonplaceholder.typicode.com/posts"
);
const listOfPosts = responseData;
for (const post of listOfPosts) {
const postEl = document.importNode(postTemplate.content, true);
postEl.querySelector("h2").textContent = post.title.toUpperCase();
postEl.querySelector("p").textContent = post.body;
listElement.append(postEl);
}
}
async function createPost(title, content) {
const userId = Math.random();
const post = {
title: title,
body: content,
userId: userId,
};
sendHttpRequest("POST", "https://jsonplaceholder.typicode.com/posts", post); // 서버에 데이터를 생성하려는 POST 요청의 경우 생성하고자하는 데이터를 나가는 요청에 추가해야한다.
}
fetchButton.addEventListener("click", fetchPost);
form.addEventListener("submit", (event) => {
event.preventDefault();
const enteredTitle = event.currentTarget.querySelector("#title").value;
const enteredContent = event.currentTarget.querySelector("#content").value;
createPost(enteredTitle, enteredContent);
});
const postList = document.querySelector("ul");
async function fetchPost() {
const responseData = await sendHttpRequest(
"GET",
"https://jsonplaceholder.typicode.com/posts"
);
const listOfPosts = responseData;
for (const post of listOfPosts) {
const postEl = document.importNode(postTemplate.content, true);
postEl.querySelector("h2").textContent = post.title.toUpperCase();
postEl.querySelector("p").textContent = post.body;
postEl.querySelector("li").id = post.id; // 추가
listElement.append(postEl);
}
}
postList.addEventListener("click", (e) => {
if (e.target.tagName === "BUTTON") {
const postId = e.target.closest("li").id;
sendHttpRequest(
"DELETE",
`https://jsonplaceholder.typicode.com/posts/${postId}`
);
}
});
function sendHttpRequest(method, url, data) {
const promise = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.responseType = "json";
xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 300) {
// xhr.status 코드를 이용해서 오류 처리
// success
resolve(xhr.response);
} else {
reject(new Error("Something went wrong!"));
}
};
xhr.onerror = function () {
reject(new Error("Failed to send request!"));
};
xhr.send(JSON.stringify(data));
});
return promise;
}
async function fetchPost() {
try {
// try ~ catch 문 적용하여 오류 처리
const responseData = await sendHttpRequest(
"GET",
"https://jsonplaceholder.typicode.com/pos"
);
const listOfPosts = responseData;
for (const post of listOfPosts) {
const postEl = document.importNode(postTemplate.content, true);
postEl.querySelector("h2").textContent = post.title.toUpperCase();
postEl.querySelector("p").textContent = post.body;
postEl.querySelector("li").id = post.id;
listElement.append(postEl);
}
} catch (error) {
alert(error.message);
}
}
fetch() API 사용하기const listElement = document.querySelector(".posts");
const postTemplate = document.getElementById("single-post");
const form = document.querySelector("#new-post form");
const fetchButton = document.querySelector("#available-posts button");
const postList = document.querySelector("ul");
function sendHttpRequest(method, url, data) {
// const promise = new Promise((resolve, reject) => {
// const xhr = new XMLHttpRequest();
// xhr.open(method, url);
// xhr.responseType = "json";
// xhr.onload = function () {
// if (xhr.status >= 200 && xhr.status < 300) {
// // success
// resolve(xhr.response);
// } else {
// reject(new Error("Something went wrong!"));
// }
// };
// xhr.onerror = function () {
// reject(new Error("Failed to send request!"));
// };
// xhr.send(JSON.stringify(data)); // 요청 전송
// });
// return promise;
// ==================== fetch API ====================
return fetch(url).then((response) => {
return response.json();
});
}
async function fetchPost() {
try {
const responseData = await sendHttpRequest(
"GET",
"https://jsonplaceholder.typicode.com/posts"
);
const listOfPosts = responseData;
for (const post of listOfPosts) {
const postEl = document.importNode(postTemplate.content, true);
postEl.querySelector("h2").textContent = post.title.toUpperCase();
postEl.querySelector("p").textContent = post.body;
postEl.querySelector("li").id = post.id;
listElement.append(postEl);
}
} catch (error) {
alert(error.message);
}
}
async function createPost(title, content) {
const userId = Math.random();
const post = {
title: title,
body: content,
userId: userId,
};
sendHttpRequest("POST", "https://jsonplaceholder.typicode.com/posts", post);
}
fetchButton.addEventListener("click", fetchPost);
form.addEventListener("submit", (event) => {
event.preventDefault();
const enteredTitle = event.currentTarget.querySelector("#title").value;
const enteredContent = event.currentTarget.querySelector("#content").value;
createPost(enteredTitle, enteredContent);
});
postList.addEventListener("click", (e) => {
if (e.target.tagName === "BUTTON") {
const postId = e.target.closest("li").id;
sendHttpRequest(
"DELETE",
`https://jsonplaceholder.typicode.com/posts/${postId}`
);
}
});
fetch() : GET → 자체적으로 프로미스를 사용하는 APIfetch() API를 이용해 데이터 POST하기return fetch(url, {
method: method,
body: JSON.stringify(data),
}).then((response) => {
return response.json();
});
function sendHttpRequest(method, url, data) {
const xhr = new XMLHttpRequest();
xhr.setRequestHeader("Content-Type", "application/json");
...
return fetch(url, {
method: method,
body: JSON.stringify(data),
headers: {
"Content-Type": "application/json",
},
}).then((response) => {
return response.json();
});
}
application/json : JSON 데이터를 갖고 전송되는 요청에 추가되는 일반적인 헤더 중 하나. 서버에게 이 요청에 JSON 데이터가 있다고 전해주는 것return fetch(url, {
method: method,
body: JSON.stringify(data),
headers: {
"Content-Type": "application/json",
},
})
.then((response) => {
if (response.status >= 200 && response.status < 300) {
return response.json();
} else {
return response.json().then((errData) => {
console.log(errData);
throw new Error("Something went wrong - server-side !");
});
}
})
.catch((err) => {
console.log(err);
throw new Error("Something sent wrong!");
});
FormData의 장점
append를 이용하면 파일르 추가하는 것도 쉽다.const fd = new FormData(form) : 문서에 있는 form 요소를 찾아냄. 자동으로 해당 form에서 모든 데이터 수집.name="" 속성이 존재해야한다.const listElement = document.querySelector(".posts");
const postTemplate = document.getElementById("single-post");
const form = document.querySelector("#new-post form");
const fetchButton = document.querySelector("#available-posts button");
const postList = document.querySelector("ul");
function sendHttpRequest(method, url, data) {
return fetch(url, {
method: method,
// body: JSON.stringify(data),
body: data,
// headers: {
// "Content-Type": "application/json",
// },
})
.then((response) => {
if (response.status >= 200 && response.status < 300) {
return response.json();
} else {
return response.json().then((errData) => {
console.log(errData);
throw new Error("Something went wrong - server-side !");
});
}
})
.catch((err) => {
console.log(err);
throw new Error("Something sent wrong!");
});
}
async function createPost(title, content) {
const userId = Math.random();
const post = {
title: title,
body: content,
userId: userId,
};
const fd = new FormData(form); // 문서에 있는 form 요소를 찾아냄. 자동으로 해당 form에서 모든 데이터 수집.
fd.append("title", title);
fd.append("body", content);
fd.append("userId", userId);
sendHttpRequest("POST", "https://jsonplaceholder.typicode.com/posts", fd);
// sendHttpRequest("POST", "https://jsonplaceholder.typicode.com/posts", post);
}
<input type="text" id="title" name="title" />
<textarea rows="3" id="content" name="body"></textarea>
모든 API에서 FormData를 쓸 수 있는 것은 아니다.