javascript - 비동기 프로그래밍 (1)

김동하·2020년 9월 21일
0

javascript

목록 보기
24/58

자바스크립트는 동기적이다. 호이스팅 이후 동기적으로 코드를 처리한다.

호이스팅이란 var와 함수 선언들이 최상단으로 올라가는 것.

콜백엔 두 가지가 있다. 즉각적 동기적으로 실행하는 Synchoronous call back 그리고 언제 실행되는지 예측 불가인 Asynchoronous가 있다.

Synchoronous call back

console.log("1")
setTimeout(() => console.log(2), 1000)
console.log(3)

function printImmi(print){
  print()
}

printImmi(()=>console.log("hi")) // hi

setTimeout을 건 console과 순차적으로 실행하는 console.log가 있다. 얘들은 아래 사진처럼 1,3이 먼저 출력되고 1초 뒤에 2가 출력된다.

그리고 printImmi() 함수를 만들고 인자로 print라는 콜백 함수를 받아 바로 실행한다. 그리고 printImmi()을 호출한다. 인자 없이 console.log를 출력하는 함수를 전달한다.

1과 3 hi가 출력되고 2가 출력된다. 호출 과정을 정리하면 런타임을 하자마자 함수 선언부는 호이스팅이 되므로 가장 최상단으로 간다.

그리고 1 => setTimeout => 3 => printImmi(()=>console.log("hi")) => print() => 2 순으로 진행된다.

Asynchoronous

function printWithDelay(print, delay){
  setTimeout(print, delay)
}

printWithDelay(()=>console.log("async callback"), 2000)

위 코드에 printWithDelay 함수를 추가했다. 그 안에는 print와 delay를 인자로 받는 setTimeout 함수가 있다. printWithDelay 함수를 호출할 때 console.log()를 출력하는 함수와 2초의 delay를 주면

호이스팅으로 보면 함수 선언부들은 최상단에 가고 1 출력 => setTimeout() 브라우저 요청 => 3 출력 => printImmi(()=>console.log("hi")) 호출 => print() 호출 (hi 출력) => printWithDelay() 브라우저 요청 => 1초 후 setTimeout() 실행 => 2초 후 printWithDelay() 실행

콜백 지옥

class UserStorage {
    loginUser(id, password, onSuccess, onError) {
        setTimeout(() => {
            if (
                (id === "dongha" && password === 1234) ||
                (id = "dongeun" && password === 1234)
            ) {
                onSuccess(id)
            } else {
                onError(new Error("not found"))
            }
        }, 2000)

    }
    getRoles(user, onSuccess, onError) {
        setTimeout(() => {
            if (user === "dongha") {
                onSuccess({
                    name: "dongha",
                    role: "admin"
                })
            } else {
                onError(new Error("no access"))
            }
        }, 1000)
    }
}

먼저 사용자의 id, pass input 을 받는다. 그리고 서버에 전달하고 로그인이 onSuccess하면 로그인된 id를 다시 받는다. 받아온 id를 role에 요청한다. 그리고 role를 성공적으로 받으면 사용자의 obj를 받게 된다.

const userStorage = new UserStorage()
const id = prompt("id")
const password = prompt("password")
userStorage.loginUser(
    id,
    password,
    (user) => {
        userStorage.getRoles(
            user,
            (userWithRole) => {},
            (error) => {}
        )
    },
    (error) => {
        console.log(error)
    }
)

일단 정보를 받으면 userStorage.loginUser에 id, password를 전달하고 성공할 경우 사용자의 data를 받는 코드 블럭과 실패했을 때 에러 코드 블럭을 만든다.

userStorage.loginUser(
  id,
  password,
  user => {},
  error => {console.log(error)}

사용자가 로그인 되었다면 getRoles에서 사용자의 역할을 받아야 한다. 그때도 role을 받는 경우와 실패하는 경우를 전달한다.

userStorage.loginUser(
  id,
  password,
  user => {
    userStorage.getRoles(
    user, 
    (userWithRole) =>{
      alert(`id = ${userWithRole.name}, role = ${userWithRole.role}`)
    },
    error => {console.log(error)} 
    )
  },
  error => {console.log(error)}

로그인 성공

실패시

문제점

콜백 안에서 호출하고 호출하면 일단 가독성이 떨어진다. 에러가 발생한 경우 디버깅도 힘들어 진다.

그래서 promise와 await을 사용해야 한다.

출처 : https://www.youtube.com/watch?v=s1vpVCrT8f4&list=PLv2d7VI9OotTVOL4QmPfvJWPJvkmv6h-2&index=11

profile
프론트엔드 개발

0개의 댓글