19. 비동기

Lia·2023년 5월 17일
0

Underbar

자바스크립트 내장 메서드가 어떻게 콜백(Callback) 함수를 활용하는지

비동기

동기: 특정 코드의 실행이 완료될 때까지 기다리고 난 후 다음 코드를 수행하는 것’

비동기: 특정 코드의 실행이 완료될 때까지 기다리지 않고 다음 코드들을 수행하는 것

타이머 관련 API

setTimeout

setTimeout 함수는 두 개의 매개변수를 받습니다. 첫 번째 매개변수는 실행할 콜백 함수이고, 두 번째 매개변수는 지연 시간을 나타내는 밀리초 단위의 숫자입니다.
화살표 함수는 2초 후에 실행될 콜백 함수

setTimeout(() => {
  // 실행할 콜백 함수 내용
  console.log("2초 후에 실행됩니다.");
}, 2000);

clearTimeout

setTimeout 함수를 사용하여 생성한 타이머를 취소하는 데 사용됩니다. 이를 위해 clearTimeout 함수에는 setTimeout 함수의 반환된 타이머 식별자를 넣습니다.
setTimeout 함수를 호출하면 해당 호출은 타이머 식별자를 반환합니다. 이 식별자는 clearTimeout 함수에 전달되어 해당 타이머를 취소할 수 있습니다.

const timerId = setTimeout(() => {
  console.log("타이머 콜백 함수 실행");
}, 2000);

// 타이머 취소
clearTimeout(timerId);

setTimeout 함수 호출 이후 반환된 타이머 식별자인 timerId를 clearTimeout 함수에 전달하여 해당 타이머를 취소합니다. 이렇게 하면 예정된 타이머 콜백 함수가 실행되지 않습니다.

setInterval

clearInterval

Callback 함수

Callback 함수를 통해 비동기 코드의 순서를 제어할 수 있습니다.

1 다음에 2 나오게 하기.
first 함수를 호출하면서 add1 매개변수로 전달 된 second함수가 호출됨

 function first(add1){
    console.log(1)
    add1()
 }

 function second (){
    console.log(2)
 }

first(second);

굳이 왜 이렇게 쓰는지?
협업할 때 first 만들었는데 팀원들이 자주씀. first다음에 console.log(4)하고 싶은데요?
하면 필요함. 파라미터를 넣고, first안에 함수 넣어주면 되니까

Promise

비동기로 작동하는 코드를 제어할 수 있는 다른 방법은 Promise를 활용하는 방법입니다.
Promise 객체는 비동기 작업이 완료되었을 때 결과를 반환하거나 실패를 처리하기 위해 사용됩니다.

romise 객체는 생성자 함수에 executor(실행자)라고 불리는 콜백 함수를 전달하여 생성됩니다. executor 함수는 resolve와 reject라는 두 개의 콜백 함수를 인자로 받습니다. resolve 함수는 비동기 작업이 성공적으로 완료되었을 때 호출되며, reject 함수는 작업이 실패했을 때 호출됩니다.

const promise = new Promise(function(resolve, reject) {
  console.log("하하하");
});

(function(resolve, reject) {
  console.log("하하하");//  콜백함수(executor) resolve,reject 는 콜백함수의 매개변수지
  
 arrow 함수로 사용함. 
 
 const promise = new Promise((resolve, reject) => {
console.log("이렇게")
});

promise를 만드는 순간 함수가 바로 실행됨.
코드가 정상적으로 처리가 되었다면 resolve 함수를 호출하고,
에러가 발생했을 경우에는 reject 함수를 호출함

// 2초정도 일하다가 마무리하여 resolve 콜백함수를 호출하면서 성공이라는 값을 promise 객채로 전달해줌

const promise = new Promise((resolve, reject) => {
    console.log("이렇게");
    setTimeout(() => {
        resolve("aa");
    }, 1000);
  });

짠 promise를 출력해보면 "aa"가 있음~

then, catch, finally 메서드 사용

then 메서드 사용

const dd = new Promise ((resolve, reject) => {
   console.log('출력');
   setTimeout(() => {
       resolve('2초후에 출력해주세용')
   },2000);
});
dd.then(value => {
   console.log(value);
})

catch 메서드 사용

const promise = new Promise ((resolve, reject) => {
    console.log('출력');
    setTimeout(() => {
        reject(new Error('no network')); 
    },2000);
});

promise.catch(error => {
    console.log(error);
});

finally 메서드 사용

const promise = new Promise ((resolve, reject) => {
    console.log('출력');
    setTimeout(() => {
        reject(new Error('no network')); 
    },2000);
});

promise
.catch(error => {
    console.log(error);
})

.finally(() => {
    console.log('finally');
});

Promise chaining

const fetchNumber = new Promise ((resolve, reject) => {
    setTimeout(() => resolve(1),1000);
})

fetchNumber
.then(num => num * 2) // 1이 num으로 전달됨 //num = 2 
.then(num => num * 3) // num = 6
.then(num => { // 6
    // 새로운 Promise를 전달
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve(num -1 ), 1000); //num은 5
    }) //숫자를 다른서버에 보내서 다른숫자로 변환된 값을 받아옴.
})
.then(num => console.log(num)); //5 

// then은 값을 전달할수 있고 Promise를 전달해도됨
// 최종값이 나오기까지 총 2초 소요

Promise.all()

Promise.all()은 여러 개의 비동기 작업을 동시에 처리하고 싶을 때 사용합니다.
해당 배열에 있는 모든 Promise에서 executor 내 작성했던 코드들이 정상적으로 처리가 되었다면 결과를 배열에 저장해 새로운 Promise를 반환해 줍니다. 인자로는 배열을 받음!

const promiseOne = () => new Promise((resolve, reject) => setTimeout(() => resolve('1초'), 1000));
const promiseTwo = () => new Promise((resolve, reject) => setTimeout(() => resolve('2초'), 2000));
const promiseThree = () => new Promise((resolve, reject) => setTimeout(() => resolve('3초'), 3000));
// 기존
const result = [];
promiseOne()
  .then(value => {
    result.push(value);
    return promiseTwo();
  })
  .then(value => {
    result.push(value);
    return promiseThree();
  })
  .then(value => {
    result.push(value);
   console.log(result);  
	 // ['1초', '2초', '3초']
  })

Promise.all()은 비동기 작업들을 동시에 처리합니다. 따라서 3초 안에 모든 작업이 종료됩니다.

// promise.all
Promise.all([promiseOne(), promiseTwo(), promiseThree()])
  .then((value) => console.log(value))
  // ['1초', '2초', '3초']
  .catch((err) => console.log(err));

Promise.all()은 인자로 받는 배열에 있는 Promise 중 하나라도 에러가 발생하게 되면 나머지 Promise의 state와 상관없이 즉시 종료됨. 1초 후에 에러가 발생하고 Error: 에러1이 반환된 후로는 더 이상 작동하지 않고 종료.

Promise.all([
	new Promise((resolve, reject) => setTimeout(() => reject(new Error('에러1'))), 1000),
	new Promise((resolve, reject) => setTimeout(() => reject(new Error('에러2'))), 2000),
	new Promise((resolve, reject) => setTimeout(() => reject(new Error('에러3'))), 3000),
])
	.then((value) => console.log(value))
  .catch((err) => console.log(err));
	// Error: 에러1

Async/Await

Promise 코드를 간결하게 작성할 수 있게 됨.
함수 앞에 async 키워드를 사용하고 async 함수 내에서만 await 키워드를 사용하면 됨.
이렇게 작성된 코드는 await 키워드가 작성된 코드가 동작하고 나서야 다음 순서의 코드가 동작.

async

async function userName () {
    // 10 sec...
    return 'Lia'
}

userName().then(value => {
 	console.log(value);
 })

await

// 비동기 작업을 위한 함수 선언
function delay(ms) {
  // 지정된 시간(ms)만큼 대기 후에 Promise를 해결(resolve)하는 함수를 반환
  return new Promise(resolve => setTimeout(resolve, ms));
}

// 비동기 함수 userName 정의
async function userName() {
  // 6초 대기
  await delay(6000);
  // 'Lia'를 반환
  return 'Lia';
}

// userName 함수 호출 및 처리
userName().then(value => {
  // 반환된 값인 'Lia'를 출력
  console.log(value);
});

정리

  1. resolve가 가지고 있는 메소드를 호출해야만 Promise 객체의 상태가 성공(fulfilled) 상태로 변경(then)

  2. 메소드는 객체에 속하는 함수

  3. resolve(1)은 Promise객체의 성공상태값을 1로 설정하고, then 메서드를 사용하여 Promise 객체의 성공 상태값을 받아옴. then 매개변수에는 resolve 함수에서 전달된 1값이 할당되어 출력됨.

    const promise = new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(1);
        }, 2000);
      });
    
      promise.then(value => {
        console.log(value); // 출력: 1
      });
  4. 이 두코드의 차이가 헷갈렸는데 이해했다. () 익명함수로 정의했다는 것의 차이. ^^
    익명 함수의 내부에 비동기 작업과 Promise 객체 생성이 모두 포함되어 있고, 이 함수가 promiseOne 변수에 할당되어 사용됨

      const promiseOne = () => new Promise((resolve, reject) => setTimeout(() => resolve('1초'), 1000));
    const fetchNumber = new Promise ((resolve, reject) => {
          setTimeout(() => resolve(1),2000);})
profile
https://lia-portfolio.vercel.app/

0개의 댓글