09. promise(),async() await()

김선심·2023년 3월 10일
0

JavaScript

목록 보기
20/20

2023.3.4 study

참조 https://ko.javascript.info
https://yoo11052.tistory.com/155
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise/Promise

promises().then().catch();
async().await()

1. promise()

  • 비동기 작업의 최종 완료 또는 실패를 나타내는 객체이다.
    '비동기' : 특정 코드의 실행이 완료될 때까지 기다리지 않고, 다음 코드를 먼저 수행하는 특성을 가진다.
  • promise()는 객체이기 때문에 생성자 함수를 const pormise = () => new promise(resolve, reject) 인자로 전달받은 콜백 함수를 인자로 전달 받고, 인자로 받은 콜백 함수 내부에서 비동기 처리를 한다.
  • 비동기 처리가 성공(fulfilled)(resolve)가 호출된 경우 또는 실패(rejected)reject함수가 호출된 경우 실패 상태 정보를 갖게 된다.
※주의※

$.ajax({..}) /// promise x
axios({...}) /// promise o

1) promins() 문법

new Promise(executor)

  • executor :resolve 및 reject 인수를 전달할 실행 함수이다.
    1) Promise 객체는 new 키워드와 생성자를 사용해 만든다.
    2) 생성자는 매개변수로 "실행 함수"를 받음. 이 함수는 매개 변수로 두 가지 함수를 받아야 하는데, 첫 번째 함수(resolve)는 비동기 작업을 성공적으로 완료해 결과를 값으로 반환할 때 호출해야 하고, 두 번째 함수(reject)는 작업이 실패하여 오류의 원인을 반환할 때 호출한다.
    3) 두 번째 함수는 주로 오류 객체를 받는다.
const promise = () => new Promise((resolve, reject) => {
    let a = 1 + 1

    if(a == 2) {
        resolve('success')
    } else {
        reject('failed')
    }
})

promise().then((message) => {
    console.log('This is in the then ' + message) //성공일때
}).catch((message) => {
    console.log('This is in the catch' + message) // 에러일때 
})

2) promise() 후속 처리 메소드 then(), catch()

then()

  • 두개의 콜백 함수를 인자로 전달 받는다.
  • 첫 번쨰 콜백 함수는 성공(fulfilled, resolve 함수가 호출된 경우) 실행한다.
  • 두 번째 콜백 함수는 실패(rejectde, reject 함수가 호출된 경우) 실행한다.
  • then 메소드는 기본적으로 프로미스를 반환한다.

catch()

  • 비동기 처리 혹은 then 메소드 실행 중 발생한 에러(예외)가 발생하면 호출한다.
  • catch 메소드 역시 프로미스를 반환한다.
const promise = () => new Promise((resolve, reject) => {
    let a = 1 + 1

    if(a == 3) {
        resolve('success')
    } else {
        reject('failed')
    }
})

promise().then((message) => {
    console.log('This is in the then ' +  message)//성공
}, (error) => {
    console.log('This is in the then ' +  error)//실패
})

3) promise() 체이닝

  • 후속 처리 메소드를 체이닝하여 promise()를 반환하는 여러개의 비동기 함수들을 연결하여 사용할 수 있다.
const promise = (result) => {
    return new Promise((resolve, reject) => {
        if(result == 'success')
            resolve('success')
        else
            reject('failed')
    })
}

promise('success')
    .then(promise) // .then(result => promise(result))
    .then(message => console.log('This is in the then ' + message))
    .catch(error => console.log('This is in the catch ' + error))

4) 정적 메소드

  • promins() 5가지 정적 메소드를 제공한다.
  • 정적메소드이기 때문에 객체의 생성없이 사용 가능하다.

(1). promise.resolve

  • Promise.resolve 메소드는 인자값을 래핑하여 프로미스를 반환한다. (fulfilled)
const promise = Promise.resolve('success') // new Promise(resolve => resolve('success'))
promise.then(message => console.log('This is in the then ' + message)) 
///This is in the then success

(2). promise.rejcet

  • Promise.reject 메소드역시 인자값을 래핑하여 프로미스를 반환한다. (rejected)
const promise = Promise.reject('failed') // new Promise((resolve, reject) => reject('failed'))
promise.catch(error => console.log('This is in the catch ' + error))
///This is in the catch failed

(3). promise.all

  • Promise.all 메소드는 프로미스가 담겨있는 배열과 같은 이터러블 객체를 인자로 받는다. 인자로 전달받은 모든 프로미스를 병렬로 처리하고 그 결과값을 배열에 담아 resolve로 반환한다.
  • 서로 의존관계이지 않은 여러 프로미스들을 이터러블 객체에 담아 Promise.all 메소드를 이용해 한번에 병렬처리 할 수 있다.
  • 가장 마지막으로 끝나는 프로미스를 기준으로 수행되고, 모든 프로미스가 fullfilled 상태가 되면 결과값을 배열에 담아 새로운 프로미스를 반환한다.
  • 프로미스를 수행하던 도중 하나라도 에러(rejected)가 발생하면 rejected 상태가 되고 수행을 종료한다.
/// promise.all() 사용하지 않을 때
const promise1 = () => new Promise(resolve => setTimeout(() => resolve(1), 1000))
const promise2 = () => new Promise(resolve => setTimeout(() => resolve(2), 2000))
const promise3 = () => new Promise(resolve => setTimeout(() => resolve(3), 3000))

promise1().then(result => {
    console.log(result) // 프로그램을 실행하고 1초뒤에 수행됨
    return promise2()
}).then(result => {
    console.log(result) // 프로그램을 실행하고 3초뒤에 수행됨 (1 + 2)
    return promise3()
}).then(result => {
    console.log(result) // 프로그램을 실행하고 6초뒤에 수행됨 (1 + 2 + 3)
})
/// 1
/// 2
/// 3

///  promise.all() 사용할 때
Promise.all([
    new Promise(resolve => setTimeout(() => resolve(1), 1000)),
    new Promise(resolve => setTimeout(() => resolve(2), 2000)),
    new Promise(resolve => setTimeout(() => resolve(3), 3000))
]).then(console.log) // 프로그램을 실행하고 3초뒤에 실행됨
.catch(console.log)
/// 1, 2 , 3

(4). promise.race

  • Promise.all 메소드와 동일하게 프로미스가 담겨있는 이터러블 객체를 인자로 받지만, Promise.all 과 달리 병렬로 처리하지 않고 가장 먼저 끝나는 프로미스의 결과값을 resolve로 반환한다.
Promise.race([
    new Promise(resolve => setTimeout(() => resolve(1), 1000)),
    new Promise(resolve => setTimeout(() => resolve(2), 2000)),
    new Promise(resolve => setTimeout(() => resolve(3), 3000))
]).then(console.log) 
.catch(console.log)
/// 1

(5). promise.allSettled

  • Promise.all 메소드와 또다른 차이점은 각각의 프로미스 처리결과를 객체로 나타내고 status 프로퍼티를 가지게된다. fullfilled 상태인 경우 value 프로퍼티를 가지게되고, rejected 상태인 경우 reason 프로퍼티를 가지게된다.
  • Promise.all 메소드와 동일하게 프로미스가 담겨있는 이터러블 객체를 인자로 받고 병렬로 처리하지만, allSettled()메소드는 rejected 상태가 되어도 수행을 종료하지않고, 프로미스가 수행된 상태와 결과값을 배열에 담아 resolve로 반환한다.
Promise.allSettled([
    new Promise(resolve => setTimeout(() => resolve(1), 1000)),
    new Promise((resolve, reject) => setTimeout(() => reject(2), 2000))
]).then(console.log)
/// [
///  { status: 'fulfilled', value: 1 },
///  { status: 'rejected', reason: 2 }
/// ]

2. async()

  • 함수앞에 async를 붙이면 해당 함수는 자동으로 프로미스를 반환하게 된다.
  • 비동기로 처리되는 부분에 await를 붙이면 해당 프로미스가 끝날때까지 기다린다. (동기적으로 처리)
  • await은 async가 붙은 함수 안에서만 사용 가능하다.
  • async 함수에서 return은 resolve()와 같은 역할을 한다.
  • 문자열을 반환하는 것처럼 보이지만 실제로는 프로미스를 반환한다.
  • 프로미스를 반환하는 함수앞에 await()를 붙여 더 간편하게 동기적으로 처리할 수 있고, 프로미스를 사용해 동기적으로 처리하는 경우 fullfilled값을 then() 후속 처리 메소드를 통해 결과값을 인자로 넘겨 체인내에서 처리해야하지만, await를 사용하면 fullfilled 값을 외부로 넘겨줄 수 있다.

1)문법

async function name([param[, param[, ... param]]]) {
        statements
    }
  • name : 함수이름
  • param : 함수에게 전달되기 위한 인자의 이름.
  • statements : 함수 본문을 구성하는 내용. await 메커니즘이 사용됨.
☆ async/await ☆ 함수의 목적은 사용하는 여러 promise의 동작을 동기스럽게 사용할 수 있게 하고, 어떠한 동작을 여러 promise의 그룹에서 간단하게 동작하게 하는 것이다. promise가 구조화된 callback과 유사한 것 처럼 async/await 또한 제네레이터(generator)와 프로미스(promise)를 묶는것과 유사하다.
/// promise().than.catch
const timeout = (value, timeout) => new Promise((resolve, reject) => {
    setTimeout(() => resolve(value), timeout)
})

timeout('Hello ', 1000)                                       // 프로그램 실행후 1초뒤에 수행됨
	.then(result => {
		console.log('complete promise')
		return timeout(result + 'My Name is ', 2000)  // 프로그램 실행후 3초뒤에 수행됨(1 + 2)
	}).then(result => {
		console.log('complete promise')
		return timeout(result + 'seonsim ', 3000)       // 프로그램 실행후 6초뒤에 수행됨(1 + 2 + 3)
	}).then(result => {
		console.log('complete promise')
		console.log(result)
	})

/// complete promise
/// complete promise
/// complete promise
/// Hello My name is seonsim
-----------------------------------------------------------
/// async().await

const timeout = (value, timeout) => new Promise((resolve, reject) => {
    setTimeout(() => resolve(value), timeout)
})

async function awaitFunc() {
    let str = ''

    str += await timeout('Hello ', 1000)       // 프로그램 실행후 1초뒤에 수행됨
    console.log('complete promise')
    str += await timeout('My name is ', 2000)  // 프로그램 실행후 3초뒤에 수행됨(1 + 2)
    console.log('complete promise')
    str += await timeout('seonsim ', 3000)       // 프로그램 실행후 6초뒤에 수행됨(1 + 2 + 3)
    console.log('complete promise')

    return str
}

awaitFunc().then(console.log)

/// complete promise
/// complete promise
/// complete promise
/// Hello My name is seonsim

2) async 예외 처리 try-catch

  • sync와 await을 사용하면 프로미스를 함수 내부에서 동기적으로 처리할 수 있기 때문에 try-catch 구문을 사용 예외 처리를 할 수 있다.
  • await은 async가 붙은 함수 내에서만 사용 가능하기 때문에 최종결과나 처리되지 못한 에러의 경우 catch() 메소드를 사용해 처리해주곤 한다.
async function promise() {
    throw 'rejected';
}

async function exceptionFunc() {
    try {
        await promise()
    } catch (e) {
        console.log('catch error!', e)
    }
}

exceptionFunc()
///catch error! rejected
  • catch() 메소드와 try-catch 메소드를 혼용한 예외 처리 방법
async function promise() {
    throw 'rejected';
}

async function exceptionFunc() {
    try {
        return await promise()
    } catch (e) {
        console.log('catch error!', e)
        throw e
    }
}

exceptionFunc()
    .then(result => console.log('status : fulfilled,', result))
    .catch(error => console.log('status : rejected,', error))
//catch error! rejected
//status : rejected, rejected

정리하면서...
자바스크립트는 동적 언어이고 그래서 다양한 데이터들을 생성할 수 있는데 다양한 메소드를 잘 활용하기 위해서는 꼭 메소드들 문법 잘 알아야 겠고, 바뀐 문법들에 대해서도 찾아보고 원서를 잘 봐야할거 같다.

profile
i can do it

0개의 댓글