javascript 동기와 비동기
//비동기 함수
//실행의 순서를 지키지 않는다.
// 내가원하는 시간 뒤에 함수를 호출
console.log('1');
setTimeout(
function(){
console.log('3');
},
2000
)
console.log('2');
// 회중시계 같은 것이다
let num = 0;
let id = setInterval(() => {
console.log(num++);
}, 2000);
setTimeout(
()=>{
clearInterval(id)
console.log('exit');
},
1300
);
//비동기
for(var i = 0; i<3; i++){
setTimeout(()=>{
console.log(i);
},
1000
)
}
for(let i =0; i < 3; i++){
//즉시 실행
(function(x){
setTimeout(() => {
console.log(x);
}, i*1000);
})(i);
}
인코딩은 문자열을 부호화 시킬때를 인코딩이라고한다.
반대를 디코딩이라고 한다.
//문자
let str = '' ;
str += 'let a = 10;';
str += 'console.log(a)';
console.log(str);
//문자열을 하나의 명령어로 해석
eval(str);
javascript는 하나의 호출스택을 가진 단일 스레드 프로그램이 언어이다
자바스크립트는 하나의 호출 스택만 있기 때문에 하나의함수를 처리하면서 많은 시간이 소요되게 된다면 다음 함수를 호출하는데 지장을 줄 수 있다.
비동기의 필요성 아래와 같은 방법으로 이 문제를 해결
- 비동기적 callback 함수 사용
- ES6 Promise
- ES8 async await
call back
콜백 함수란 다른 함수의 인자로 이용되는 함수이며 어떤 이벤트에 의해 호출되는 함수이다.
콜백 함수는 아래 코드와 같이 동기적으로 사용될 수도 있다.
//call back 함수
function printImmediately(callBackFunction) {
callBackFunction()
}
printImmediately(()=>console.log('synchronous callback'))
function printWithDelay(callback, sec){
setTimeout(callback, sec*1000)
}
printWithDelay(()=>console.log("async callback"), 2)
console.log("hello")
Promise
콜백 함수를 사용하지 않고 Promise objecct를 통해 비동기 함수를 처리
const initialPokemon = () =>
new Promise((resolve, reject)=>{
setTimeout(()=>resolve('파이리'), 1000)
});
const nextPokemon = prevPokemon =>
new Promise((resolve, reject)=>{
setTimeout(()=>resolve(`${prevPokemon} => 리자드`), 1000)
});
const finalPokemon = prevPokemon =>
new Promise((resolve, reject)=>{
setTimeout(()=>resolve(`${prevPokemon} => 리자몽`), 1000)
});
initialPokemon() // 1초 소요
.then(prev=>{
console.log(prev) // 파이리
return nextPokemon(prev) // 1초 소요
})
.then(prev=>{
console.log(prev) // 파이리 => 리자드
return finalPokemon(prev) // 1초 소요
})
.then(console.log) // 파이리 => 리자드 => 리자몽
async await
async wait을 사용하면 promise를 깔끔한 스타일로 작성할 수 있다. 하지만 무조건 async await이 절대적으로 깔끔한 방법은 아니고 상황에 맞게 사용하여야 한다.
async키워드는 함수 앞에 붙이는 키워드이며 await 키워드는 async 키워드가 붙어 있는 함수 내부에서만 사용할 수 있다. awiat 라는 코드로 의도한 순서대로 코드의 흐름을 제어 할 수 있다.
주의할 점은 async 함수를 호출할 때 명시적으로 promise 객체를 생성하여 리턴하지 않아도 promise 객체가 리턴
호출하는 코드는 then() 메서드를 사용하여 결과값을 출력
async awiat의 또다른 장점은 동기와 비동기 구분 없이 try catch로 일관된 예외 처리가 가능하다.
const myFunction = async (postId) => {
const postResponse = await fetch(
`https://jsonplaceholder.typicode.com/posts/${postId}`
)
const post = await postResponse.json()
const userId = post.userId
try {
const userResponse = await fetch(
// 1번 주소: `https://jsonplaceholder.typico`
// 2번 주소: `https://jsonplaceholder.typicode.com/users/${userId}`
)
const user = await userResponse.json()
return user.name || "no data"
} catch (err) {
console.log(err)
return "Unknown"
}
}
myFunction(15).then(console.log)
Promise APIs
Promise all
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(alert); // 프라미스 전체가 처리되면 1, 2, 3이 반환됩니다. 각 프라미스는 배열을 구성하는 요소가 됩니다.
에러가 발생하면 다른 프라미스는 무시됩니다.
프라미스가 하나라도 거부되면 Promise.all은 즉시 거부되고 배열에 저장된 다른 프라미스의 결과는 완전히 잊힙니다. 이행된 프라미스의 결과도 무시되죠.
fetch를 사용해 호출 여러 개를 만들면, 그중 하나가 실패하더라도 호출은 계속 일어납니다. 그렇더라도 Promise.all은 다른 호출을 더는 신경 쓰지 않습니다. 프라미스가 처리되긴 하겠지만 그 결과는 무시됩니다.
프라미스에는 '취소’라는 개념이 없어서 Promise.all도 프라미스를 취소하지 않습니다.
Promise race
Promise.all과 비슷합니다. 다만 가장 먼저 처리되는 프라미스의 결과(혹은 에러)를 반환합니다.
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
Promise resolve
Promise.resolve(value)는 결괏값이 value인 이행 상태 프라미스를 생성합니다.
아래 코드와 동일한 일을 수행합니다.
let promise = new Promise(resolve => resolve(value));
Promise reject
Promise.reject(error)는 결괏값이 error인 거부 상태 프라미스를 생성합니다.
아래 코드와 동일한 일을 수행합니다.
let promise = new Promise((resolve, reject) => reject(error));
Promise 클래스에는 5가지 정적 메서드가 있습니다.
- Promise.all(promises) – 모든 프라미스가 이행될 때까지 기다렸다가 그 결괏값을 담은 배열을 반환합니다. 주어진 프라미스 중 하나라도 실패하면 Promise.all는 거부되고, 나머지 프라미스의 결과는 무시됩니다.
- Promise.allSettled(promises) – 최근에 추가된 메서드로 모든 프라미스가 처리될 때까지 기다렸다가 그 결과(객체)를 담은 배열을 반환합니다. 객체엔 다음과 같은 정보가 담깁니다.
- status: "fulfilled" 또는 "rejected"
- value(프라미스가 성공한 경우) 또는 reason(프라미스가 실패한 경우)
- Promise.race(promises) – 가장 먼저 처리된 프라미스의 결과 또는 에러를 담은 프라미스를 반환합니다.
- Promise.resolve(value) – 주어진 값을 사용해 이행 상태의 프라미스를 만듭니다.
- Promise.reject(error) – 주어진 에러를 사용해 거부 상태의 프라미스를 만듭니다.
자세한 사항은
https://ko.javascript.info/promise-api
프라미스 API
ko.javascript.info
참고하세요