콜백
: 나중에 호출할 함수
: 특정 함수의 실행이 완료 되면서 실행되는 함수
: 특정 함수 내에서 실행되는 함수
function loadScript(src, callback) {
let script = document.createElement('script');
script.src = src;
script.onload = () => callback(script);
document.head.append(script);
}
function loadScript(src, callback) {
let script = document.createElement('script');
script.src = src;
script.onload = () => callback(script);
document.head.append(script);
}
loadScript('https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.2.0/lodash.js', script => {
alert(`${script.src}가 로드되었습니다.`);
alert( _ ); // 스크립트에 정의된 함수
});
콜백 속 콜백
: 콜백 함수 안에서 콜백을 실행
loadScript('/my/script.js', function(script) {
loadScript('/my/script2.js', function(script) {
loadScript('/my/script3.js', function(script) {
// 세 스크립트 로딩이 끝난 후 실행됨
});
})
});
에러 핸들링 (오류 우선 콜백)
: 함수 실행 중 발생하는 에러를 처리
loadScript('/my/script.js', function(error, script) {
if (error) {
// 에러 처리
} else {
// 스크립트 로딩이 성공적으로 끝남
}
});
멸망의 피라미드 (콜백 지옥)
: 함수의 호출이 중첩되면서 코드가 깊어지는 코드
: 비동기 동작이 하나씩 추가 될 때마다 중첩호출이 만들어내는 피라미드가 오른쪽으로 커짐
loadScript('1.js', function(error, script) {
if (error) {
handleError(error);
} else {
// ...
loadScript('2.js', function(error, script) {
if (error) {
handleError(error);
} else {
// ...
loadScript('3.js', function(error, script) {
if (error) {
handleError(error);
} else {
// 모든 스크립트가 로딩된 후, 실행 흐름이 이어집니다. (*)
}
});
}
})
}
});
멸망의 피라미드 해결 (콜백지옥 해결)
: 각 비동기 동작을 독립적인 함수로 만들어 완화
loadScript('1.js', step1);
function step1(error, script) {
if (error) {
handleError(error);
} else {
// ...
loadScript('2.js', step2);
}
}
function step2(error, script) {
if (error) {
handleError(error);
} else {
// ...
loadScript('3.js', step3);
}
}
function step3(error, script) {
if (error) {
handleError(error);
} else {
// 모든 스크립트가 로딩되면 다른 동작을 수행합니다. (*)
}
};
프라미스 (Promise)
- 제작코드
: 원격에서 실행되는 코드
- 소비코드
: 제작코드의 결과를 기다렸다가 실행되는 코드
- 프라미스
: 제작코드와 소비코드를 이어주는 자바스크립트 객체
: 시간이 얼마나 걸리든 상관없이 약속한 결과를 만들어냄
let promise = new Promise(function(resolve, reject) {
// executor (제작 코드)
});
: new Promise에 전달되는 함수는 executer (실행자 / 실행함수)라고 함
: executer는 new Promise가 만들어질때 자동으로 실행되며 결과를 최종적으로 만들어내는 제작코드를 포함함
- resolve (value)
: 작업이 성공적으로 끝난 경우 그 결과를 나타내는 value와 함께 호출
- reject (error)
: 작업 중 에러 발생 시 에러 객체를 나타내는 error와 함께 호출
Promise의 상태와 단계
- state
: pending (보류) > resolve 호출 > fulfilled (result로 value 반환)
: pending (보류) > reject 호출 > rejected (result로 error 반환)
let promise = new Promise(function(resolve, reject) {
// 프라미스가 만들어지면 executor 함수는 자동으로 실행됩니다.
// 1초 뒤에 일이 성공적으로 끝났다는 신호가 전달되면서 result는 'done'이 됩니다.
setTimeout(() => resolve("done"), 1000);
});
let promise = new Promise(function(resolve, reject) {
// 1초 뒤에 에러와 함께 실행이 종료되었다는 신호를 보냅니다.
setTimeout(() => reject(new Error("에러 발생!")), 1000);
});
※ 프라미스는 resolve나 reject 중 하나를 반드시 호출해야함
: 처리가 끝난 프라미스에 resolve와 reject를 호출하면 무시됨
let promise = new Promise(function(resolve, reject) {
resolve("done");
reject(new Error("…")); // 무시됨
setTimeout(() => resolve("…")); // 무시됨
});
resolve, reject 즉시 호출하기
let promise = new Promise(function(resolve, reject) {
// 일을 끝마치는 데 시간이 들지 않음
resolve(123); // 결과(123)를 즉시 resolve에 전달함
});
: 프라미스 객체의 state와 result 프로퍼티는 내부 프로퍼티이므로 개발자가 직접 접근할 수 없음
: .then, .catch, .finally를 메서드를 사용하면 접근 가능
소비코드
- .then
: 프라미스가 이행되었을 때 실행되는 함수를 불러오는 메서드
promise.then(
function(result) { /* 결과(result)를 다룹니다 */ },
function(error) { /* 에러(error)를 다룹니다 */ }
);
let promise = new Promise(function(resolve, reject) {
setTimeout(() => resolve("done!"), 1000);
});
// resolve 함수는 .then의 첫 번째 함수(인수)를 실행합니다.
promise.then(
result => alert(result), // 1초 후 "done!"을 출력
error => alert(error) // 실행되지 않음
);
let promise = new Promise(resolve => {
setTimeout(() => resolve("done!"), 1000);
});
promise.then(alert); // 1초 뒤 "done!" 출력
- .catch
: 에러가 발생한 경우만 다룰때 사용하는 메서드
: .then(null, errorHandlingFunction)과 같이 null을 인수로 전달하는 것과 같음
let promise = new Promise((resolve, reject) => {
setTimeout(() => reject(new Error("에러 발생!")), 1000);
});
// .catch(f)는 promise.then(null, f)과 동일하게 작동합니다
promise.catch(alert); // 1초 뒤 "Error: 에러 발생!" 출력
- .finally
: 프라미스가 이행되고 나서 결과에 상관없이 실행되는 메서드
: .finally 뒤에 .then과 .catch를 사용하여 오류처리 등등을 할 수 있음
new Promise((resolve, reject) => {
setTimeout(() => resolve("결과"), 2000)
})
.finally(() => alert("프라미스가 준비되었습니다."))
.then(result => alert(result)); // <-- .then에서 result를 다룰 수 있음
Refference
'Programming > JavaScript' 카테고리의 다른 글
모던 자바스크립트 (promise와 async, await) 9-3. async와 await (0) | 2022.04.23 |
---|---|
모던 자바스크립트 (promise와 async, await) 9-2. 프라미스 체이닝 / 에러 핸들링 / API / 프라미스화 / 마이크로 태스크 (0) | 2022.04.23 |
모던 자바스크립트 (에러핸들링) 8-2. 커스텀 에러와 에러 확장 (0) | 2022.04.23 |
모던 자바스크립트 (에러핸들링) 8-1. try catch (0) | 2022.04.23 |
모던 자바스크립트 (클래스) 7-3. 내장 클래스 확장하기 / instanceof 로 클래스 확인 하기 / 믹스인 (0) | 2022.04.23 |