goal 💯️
- 어떤 경우에 중첩된 callback이 발생하는지 이해할 수 있다.
- 중첩된 callback의 단점, Promise 의 장점을 이해할 수 있다.
- Promise 사용 패턴과 언어적인 특징들을 이해할 수 있다.
- resolve, reject의 의미와, then, catch와의 관계를 이해할 수 있다.
- Promise 에서 인자를 넘기는 방법에 대해 이해할 수 있다.
- Promise의 세가지 상태를 이해할 수 있다.
- Promise.all 의 사용법을 이해할 수 있다.
- async/await keyword에 대해 이해하고, 작동 원리를 이해할 수 있다.
- node.js의 fs 모듈의 사용법을 이해한다.
new Promise()
resolve() // => go to next action
reject() //=> handle error
예제
// 콜백헬
const printString = (string, callback) => {
setTimeout(() => {
console.log(string)
callback()
}, Math.floor(Math.random() * 100) + 1);
}
const printAll = () => {
printString ("A", () => {
printString ("B", () => {
printString ("C", () => {})
})
})
}
printAll() // ABC
////////////////////////////////////////////////
//프로미스를 활용
const printString = (string) => {
return new Promise ((resolve, reject) => {
setTimeout(() => {
console.log(string)
resolve()
}, Math.floor(Math.random() * 100) + 1);
})
}
const printAll = () => {
printString ("A")
.then(() => {
return printString("B")
})
.then(() => {
return printString("C")
})
}
printAll()
// 콜백을 인자로 받지 않고, 새로운 인스턴스인 Promise
resolve
와 reject
함수를 인자로 전달받는다.// promise 객체생성
const promise = new Promise((resolve, reject) => {
// 여기서 비동기 작업을 수행한다.
if (/* 비동기 작업 수행 성공 */) {
resolve('success');
}
else { /* 비동기 작업 수행 실패 */
reject('failure');
}
});
상태 | 의미 |
---|---|
pending resolve or reject 함수가 아직 호출되지 않은 상태 | 비동기 처리가 아직 수행되지 않은 상태 (성공 or 실패 둘다 X) |
fulfilled resolve 함수가 호출된 상태 | 비동기 처리가 수행되어 결과값을 반환해준 상태 (성공!) |
rejected reject 함수가 호출된 상태 | 비동기 처리가 수행되었지만 실패하거나 오류가 발생한 상태 (실패ㅜ) |
settled resolve or reject 함수가 호출된 상태 | 비동기 처리가 수행된 상태 (성공 or 실패) |
const 프로미스 = true;
const promise = new Promise( (resolve,reject) => {
if (프로미스) {
resolve("성공!")
} else {
reject("실패ㅜ")
}
})
promise
.then((data) => {
console.log(data)
})
.catch((err) => {
console.error(err)
})
new Promise
로 프로미스를 생성할 수 있다.resolve
와 reject
를 매개변수로 갖는 콜백 함수를 넣어줄 수 있다.resolve
가 호출되면, then
의 내용이 실행되고,reject
가 호출되면, catch
의 내용이 실행된다.then
이나 catch
에서 다시 다른 then
, catch
를 붙일 수도 있다.then
의 메서드들은 "순차적으로 실행"된다. (가독성을 높인다)let promise = Promise.all([...promises...])
[...promises...]
이들이 모두 처리되면, 새로운 프로미스가 처리되며, 새로운 결과값은 배열에 담김then
으로 넘어갈 수 있지만, 하나라도 에러가나거나 처리가 안되면, catch
로 넘어간다. (인자가 && 연산자처럼 묶여있다고 생각하면 된다)let result = Promise.all([
new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
new Promise(resolve => setTimeout(() => resolve(3), 1000)) // 3
])
.then (console.log(result))
// 전체가 처리되면 1,2,3이 반환된다.
let urls = [
'https://api.github.com/users/iliakan',
'https://api.github.com/users/remy',
'https://api.github.com/users/jeresig'
];
// fetch를 사용해 url을 promise로 mapping
let requests = urls.map(url => fetch(url));
// Promise.all은 모든 작업이 마칠 때까지 기다린다.
Promise.all(requests)
.then(responses => responses.forEach(
response => alert(`${response.url}: ${response.status}`)
));
// 차례대로
// https://api.github.com/users/iliakan: 200,
// https://api.github.com/users/remy: 200,
// https://api.github.com/users/jeresig: 200
const path = require('path'); // path 모듈은 운영체제별로 경로 구분자가 달라 생기는 문제를 쉽게 해결하기 위해 등장
const { getDataFromFilePromise } = require('./02_promiseConstructor'); // 02에서 해당 함수를 가져옴
const user1Path = path.join(__dirname, 'files/user1.json');
const user2Path = path.join(__dirname, 'files/user2.json');
console.log(user1Path)
// /home/jungeundelilahlee/dev/codestates/PAIR/im-sprint-async-and-promise/part-2/files/user1.json
// 노드는 해당키워드(__dirname)로 경로에 대한 정보를 제공함
//! __filename : file명을 포함한 절대 경로
//! __dirname : file명을 제외한 절대경로
//! path.join : 위에처럼 나옴 (콘솔로 확인가능)
const readAllUsersChaining = () => {
return getDataFromFilePromise(user1Path)
.then((user1) => {
return getDataFromFilePromise(user2Path)
.then((user2) =>{
return `[${user1}, ${user2}]`
})
})
.then((str) => JSON.parse(str))
}
// readAllUsersChaining();
module.exports = {
readAllUsersChaining
}
const readAllUsers = () => {
//! 실패한 방법
//? let requests = [`${user1Path}, ${user2Path}`]
//? console.log(requests) // 못가져옴...
//? console.log(user1Path) // 이렇게하면 그냥 파일 path만 가져올 수 있음
//? console.log(getDataFromFilePromise(user1Path)) // pending 상태에 머무름
//? return Promise.all(requests)
//? .then((result) => {
//? let dd = []
//? for (let i = 0; i < result.length; i++) {
//? dd.push(result[i])
//? }
//? return dd
//? })
//? .then((str) => JSON.parse(str))
return Promise.all([getDataFromFilePromise(user1Path), getDataFromFilePromise(user2Path)])
.then(([u1, u2]) => {
return `[${u1}, ${u2}]`
})
.then((str) => JSON.parse(str))
}
const readAllUsersAsyncAwait = async () => {
// async
//! function 키워드 앞에 async 키워드 위치
//! function 앞에 async를 붙이면 해당 함수는 항상 프라미스를 반환
//! 프라미스가 아닌 값을 반환하더라도 이행 상태의 프라미스(resolved promise)로 값을 감싸 이행된 프라미스가 반환되도록함
//! async가 붙은 함수는 반드시 프라미스를 반환하고, 프라미스가 아닌 것은 프라미스로 감싸 반환함
// await
//! async 함수 안에서만 동작
//! 자바스크립트는 await 키워드를 만나면 프라미스가 처리(settled)될 때까지 기다림. 결과는 그 이후 반환됨
//! await는 내가 순서를 제어할 수 있음
const user1 = await getDataFromFilePromise(user1Path);
const user2 = await getDataFromFilePromise(user2Path);
const str = `[${user1}, ${user2}]`;
return JSON.parse(str);
}
客户需求的变化也对作业代写 https://www.yydaixie.com 价格产生了重要影响。近年来,随着在线教育和远程学习的普及,越来越多的学生开始寻求代写服务,这使得市场需求大幅增加。同时,学生对高质量、定制化服务的需求也在不断上升,这促使代写机构提升服务质量,进而推高了价格。此外,客户需求的多样化也对价格产生影响,如对紧急订单、特殊格式和引用、专业领域写作等方面的需求增加,都导致了价格的上升。为了满足不断变化的客户需求,代写机构需要不断提升自身的服务水平和专业能力,这也反映在价格上。