문득 콜백지옥을 해결하는 방법에 대해 궁금해 검색해보았다.가만 생각해보니 콜백 함수도 제대로 모르고 있었다. 너무 기초적인 내용일진 데도 불구하고 콜백 함수를 검색하니 결국 동기 비동기에 대해 기본적인 지식을 확실하게 짚고 넘어가려고 한다.
동기(Synchronized) 란 코드가 작성된 순서대로 프로그램이 실행되는 것을 말한다.
console.log('Start'); // 1
console.log('go'); // 2
console.log('end'); // 3
1 > 2 > 3
위와 같은 순서로 코드가 실행되며 상위 코드가 작업을 마치기 전까지 아래 내용의 코드가 실행되지 않는다. (하향 진행)
이름만 들어도 위의 동기와 반대개념으로 유추된다.
javascript
는 ⭐️싱글스레드⭐️ 이기 때문에 한번에 하나의 작업만 수행가능 하다. 이를 극복하기 위해 비동기가 존재한다. 비동기는 이전 코드의 작업 완료 여부와 관계없이 실행된다.
스레드(Thread)
스레드는 어떠한 프로그램 내에서, 특히 프로세스 (운영체제로부터 자원을 할당받는 작업의 단위) 내에서 실행되는 흐름의 단위를 말한다. 일반적으로 한 프로그램은 하나의 스레드를 갖고 있지만, 프로그램 환경에 따라 둘 이상의 스레드를 동시에 실행할 수 있다.
대충 카페에 알바생이 하나인 경우로 이해
싱글스레드의 경우 코드를 다중으로 작업할 수 없다라고 이해
다음에 스레드에 관해 자세하게 공부할 예정
console.log('Start')
setTimeout(function() {
console.log('5초 후 실행')
}, 5000)
console.log('End')
setTimeout()
은 javascript
에서 대표적으로 사용되는 비동기 처리 이다.
위처럼 작성 시 'Start' 'End' 가 콘솔에 출력된 타임라인과 상관없이 5초(5000ms) 뒤에 '5초 후 실행' 메시지가 콘솔에 출력된다.
콜백함수(Callback Function)란 파라미터로 함수를 전달받아, 함수의 내부에서 실행하는 함수이다. 함수 안의 함수라 할 수 있다. 함수 이름 없이 익명으로도 전달이 가능하다.
let number = [1, 2, 3, 4, 5];
number.forEach(x => {
console.log(x * 2); // forEach 라는 함수안에
});
// 2 4 6 8 10
function introduce (lastName, firstName, callback) {
var fullName = lastName + firstName;
callback(fullName);
}
introduce("홍", "길동", function(name) {
console.log(name);
});
내 오해와 진실
⭐️함수를 매개변수로 받는 introduce()
가 아닌 introduce()
의 매개변수인 callback
이 콜백함수 인 것이여따!⭐️
const hyunwoo = (callback) => {
let vegetable = '오이';
callback(vegetable);
}
const hateFood = (food) => {
console.log(food, ' 시더');
}
const likeFood = (food) => {
console.log(food,' 잇타다끼맛스');
}
hyunwoo(hateFood);
함수 내에 익명 함수가 반복되어 피라미드의 형태를 띈 코드. 예외처리를 포함하면 가독성이 매우 좋지 않게 된다.
step1(function (err, value1) {
if (err) {
console.log(err);
return;
}
step2(function (err, value2) {
if (err) {
console.log(err);
return;
}
step3(function (err, value3) {
if (err) {
console.log(err);
return;
}
step4(function (err, value4) {
// 정신 건강을 위해 생략
});
});
});
});
ECMAscript2015
에서 표준으로 지정되었다고 한다.somethingAsync(value1)
.then((result) => {
return 42;
})
.then((result) => {
return somethingAsync2(); //somethingAsync2에서 return된 값이 최종적으로 리턴된다.
})
.catch((error) => {
return new Promise((resolve, reject) => {
// 기존 방식의 비동기 작업을 수행하기 위해서는 new Promise를 이용해서 새 Promise 객체를 return하면 된다.
// 성공할 경우 resolve에 원하는 값을 넣어 실행시키면 된다. 실패는 reject로 한다.
resolve('성공');
// reject('실패');
});
})
.then((result) => {
// 위의 then이나 catch가 성공했을 경우 이쪽이 실행된다.
}, (error) => {
// catch를 사용하는 대신에 then의 두번째 인자를 사용할 수도 있다.
});
resolve reject 를 사용하여 비동기 작업 성공 여부에 따라 원하는 값을 넣어 처리할 수 있다
function f() {
return somethingAsync(value1)
.then((result) => {
// 성공시 수행할 작업
})
.catch((error) => {
// 실패시 수행할 작업
});
}
위 아래 같은 실행
async function f() {
try {
var result = await somethingAsync(value1);
// 성공시 수행할 작업
} catch (error) {
// 실패시 수행할 작업
}
}