[javaScript] 동기와 비동기

728x90

 

1. 동기

- 여러 작업이 있을 때 순서대로 처리 하는 것 (코드 순서대로 처리)

 

2. 비동기

- 여러 작업이 있을 때 순서대로 처리 X 앞 작업이 다 끝나지않아도 다음 작업 동시에 처리

- 각 작업 종료 후 결과값을 이용해 다른 동작을 수행시켜야 할 때 콜백 함수를 붙여 처리 

(1) setTimeOut 

- 코드를 특정 시간이 지난 후 비동기적으로 실행 

setTimeout( () => {
	console.log(1);
} , 3000 ); //3초만큼 기다렸다가 진행
function add(a, b){
    setTimeout(() => {
        const sum = a + b ;
        console.log(sum);
    }, 3000);
}

add(1,2); // 3초 뒤 콘솔에 3이 찍힘

 

(2) 콜백함수

function add(a, b, callback){
    setTimeout(() => {
        const sum = a + b ;
        callback(sum); //비동기 함수 안에서 콜백함수 호출하도록 설정 
    }, 3000);
}

add(1,2, (value) => {
    console.log(vale);
});

 

 

function orderfood(callback){
    setTimeout(() => {
        const food = "떡볶이";
        callback(food);
    }, 3000);
}


function cooldownFood(food, callback){
    setTimeout(() => {
        const cooldownFood = `식은 ${food}`;
        callback(cooldownFood);
    }, 2000);
}

function freezeFood(food, callback){
    setTimeout(() => {
        const freezeFood = `냉동된 ${food}`;
        callback(freezeFood)
    }, 1500);
}

orderfood((food)=>{
    console.log(food);

    cooldownFood(food, (cooldownFood) => {
        console.log(cooldownFood);

        freezeFood(cooldownFood, (freezeFood) => {
            console.log(freezeFood);
        })
    }); //비동기 작업의 결과를 또 다른 비동기 작업의 인수로 전달하는 것도 가능 
})

 

콜백 지옥을 벗어나기 위해서는 promise를 사용해야함 

 

(3) Promise

- 비동기 작업을 감싸, 감싼 비동기 작업을 실행시키거나 현재 상태를 관리 또는 결과를 저장하거나 여러개 작업을 병렬로 동시에 실행시키거나 재실행하는 등 작업 처리에 필요한 거의 모든 기능을 다 제공 

 

- 아래와 같이 코드를 작성하면 콘솔에 대기상태로 남아있는 것을 볼 수 있다.

const promise = new Promise( () => {
    //비동기 작업 실행하는 함수 ( executor )

    setTimeout(() => {
        console.log("하이");
    }, 2000);
})

console.log(promise);

 

- 다시 아래와 같이 성공을 의미하는 resolve를 실행시키더라도 콘솔에 하이가 찍힌후 promiseState가 성공(fultilled) 처리 된 것을 확인 할 수 있지만 아직도 promiseResult (결과값)은 undefined 임을 알 수 있다.

const promise = new Promise( (resolve, reject) => {
    //비동기 작업 실행하는 함수 ( executor )
    // resolve 성공 상태로 바꾸는 함수
    // reject 실패 상태로 바꾸는 함수 
    setTimeout(() => {
        console.log("하이");
        resolve();
    }, 2000);
})

setTimeout(() => {
    console.log(promise);
}, 3000);

 

- 결과값은 인수로 전달해주면 결과값이 들어간다.

const promise = new Promise( (resolve, reject) => {
    //비동기 작업 실행하는 함수 ( executor )
    // resolve 성공 상태로 바꾸는 함수
    // reject 실패 상태로 바꾸는 함수 
    setTimeout(() => {
        console.log("하이");
        resolve("안녕");
    }, 2000);
})

 

- 실패를 넘기는 경우

const promise = new Promise( (resolve, reject) => {
    //비동기 작업 실행하는 함수 ( executor )
    // resolve 성공 상태로 바꾸는 함수
    // reject 실패 상태로 바꾸는 함수 
    setTimeout(() => {
        console.log("하이");
        reject("실패한 이유...");
    }, 2000);
})

 

- then메서드 사용하기 

만약 num이 null이라 성공하지 못하면 then은 실행이 되지 않는다. then은 성공했을 때에만 실행 

대신 catch에서 잡아낼 수 있다.

const promise = new Promise( (resolve, reject) => {
    setTimeout(() => {
        const num = null;

        if(typeof num ==="number"){
            resolve(num+10);
        } else {
            reject("num이 숫자가 아님");
        }
    }, 2000);
})


//promise가 성공하면 실행하는 함수 
promise.then((value)=> {
    console.log("then 메서드를 사용했어요 --> " + value)
})

promise.catch((error)=>{
    console.log("catch 메서드를 사용했어요 --> " +error);
})

 

then과 catch를 연결하여 사용도 가능 (promise Chaining)

//promise가 성공하면 실행하는 함수 
promise.then((value)=> {
    console.log("then 메서드를 사용했어요 --> " + value)
}).catch((error)=>{
    console.log("catch 메서드를 사용했어요 --> " +error);
})

 

 

function add10(num){
    const promise = new Promise( (resolve, reject) => {
        setTimeout(() => {
            if(typeof num ==="number"){
                resolve(num+10);
            } else {
                reject("num이 숫자가 아님");
            }
        }, 2000);
    });
    return promise;
}


const p = add10(0);

p.then((result) => {
    console.log(result);
    const newP = add10(result);
    newP.then((result) => {
        console.log(result);
    })
})

위의 코드에서도 콜백 지옥이 발생할 수 있는데 promise는 이를 아래와 같이 방지시킬 수 있다.

p.then((result) => {
    console.log(result);
    const newP = add10(result);
    return newP.then((result) => {
        console.log(result);
    });;
})


//더 간단하게
add10(0).then((result) => {
    console.log(result);
    return add10(result);
}).then((result) => {
    console.log(result);
});

 

- 만약 비동기 작업이 실패하는 상황까지 catch가능 

add10(0).then((result) => {
    console.log(result);
    return add10(result);
}).then((result) => {
    console.log(result);
    return add10(undefined);
}).then((result) => {
    console.log(result);
}).catch((error) => {
    console.log(error);
});

 

 

(4) Async&Await

Async : 어떤 함수를 비동기 함수로 만들어줌. 객체를 그대로 반환하는 함수가 아니라 객체를 결과값으로 갖는 새로운 promise를 반환하는 함수로 변환됨 

async function getData1(){
    return {
        name : "홍길동",
        id :"1234",
    }
}

console.log(getData1());

콘솔을 보면 promist의 결과값을 반환되고, result에 {name:홍길동, id:1234}가 들어있다.

 

하지만 애초에 promise를 반환하고 있는 비동기 함수라면 async가 별다른 일을 하지 않고 promise 객체 자체가 반환되도록 내비둔다.

async function getData(){
   return new Promise((resolve, reject)=> {
    setTimeout(() => {
        resolve({
            name: "홍길동",
            id : "1234",
        })
    }, 1500);
   })
}

console.log(getData());

 

즉, 단순한 값만 반환하는 함수라면 async 키워드만 추가하고 promise를 리턴할 필요가 없지만 await을 사용하는 경우 async를 사용해야한다.

await : async 함수 내부에서만 사용이 가능하며 비동기 함수가 다 처리되기를 기다리는 역할을 한다.

//기존에 불편하게 쓰던 then메서드
function prontdata(){
    getData().then((result)=> {
        console.log(result);
    })
}

// await 메서드 사용
async function prontdata(){
    const data = await getData(); 
}

await 메서드를 쓰면 getData(); 가 작동을 다 하기를 기다렸다가 결과값을 data에 넣어준다.

 

728x90