
자바스크립트는 Non-blocking + Async 방식을 사용한다.
sync
async
sync/async : 특정 작업을 위한 제어흐름의 최종 마무리를 어디서 하는지에 대한 속성
A 함수에서 어떤 작업 처리를 위해 B 함수를 호출했다고 가정한다.
Blocking : B함수에서 할 일을 다 마칠때까지 A함수 제어흐름은 대기
Non-Blocking : B함수에서 할일의 완료 여부와 상관없이 곧바로 A함수쪽의 제어흐름은 이어짐
blocking/non-blocking : 제어권이 넘어갔을 때 곧바로 반환 여부에 대한 속성
XML(=Extensible Markup Language)
XMLHttpRequest
callback 코드예제
// 합이 10 미만 여부에 따라 성공/실패 응답을 하는 콜백함수를 입력받는 함수
function myFunc(p1, p2, successCallback, failCallback) {
try {
console.log("p1 + p2:", p1, p2);
result = p1 + p2;
if (result < 10) {
successCallback(result);
} else {
noWhereFunc(); // 에러 테스트
}
} catch (error) {
failCallback(error);
}
}
// 함수사용
const successFunc = function (result) {
console.log("The result is " + result);
};
const failCallback = function (error) {
console.log("Failed reason: " + error);
};
// success
myFunc(3, 4, successFunc, failCallback);
// failed
myFunc(9, 10, successFunc, failCallback);
ajax 코드예제
콜백지옥 코드예제
// 선언--
function loginUser(id, pw, onSuccess, onError) {
console.log("Match ID & PWD...");
if (pw === "correct") {
onSuccess(id);
} else {
onError("Authentication Failed...");
}
}
function getPermissions(userID, onSuccess, onError) {
console.log("Access DB and load user permissions...");
if (userID < 1000) {
let permissions = ["perm1", "perm2", "perm3"];
onSuccess(permissions);
} else {
onError("Load Permission Failed...");
}
}
// 활용 --
loginUser(
123,
"sdad123",
(userID) => {
getPermissions(
userID,
(permissions) => {
console.log("User permissions are :" + permissions);
// ... 대각선으로 계속 깊어져 가독성이 떨어짐
},
(errMsg) => {
console.log("Get user permissions failed :" + errMsg);
}
);
},
(errMsg) => {
console.log("Login user failed: " + errMsg);
}
);
promise 기본예제
let myPromise = new Promise(function (resolve, reject) {
// 성공 시 resolve()를 호출해 결과값 전달
// 실패 시 reject()를 호출해 에러를 전달
});
myPromise
.then(function (result) {
// 결과값 활용해 성공처리
})
.catch(function (err) {
// 에러객체 활용해 실패처리
})
.finally(function () {
// 공통 마무리 작업
});
resolve test
let p3 = new Promise(function (resolve, reject) {
resolve("resolve called");
});
p3.then((data) => {
console.log("p3 - then:", data);
})
.catch((error) => {
console.log("p3 - catch: ", error);
})
.finally(() => {
console.log("p3 - finally");
});
// p3 - then: resolve called
// p3 - finally
reject test
let p3 = new Promise(function (resolve, reject) {
reject("rejected called");
});
p3.then((data) => {
console.log("p3 - then:", data);
})
.catch((error) => {
console.log("p3 - catch: ", error);
})
.finally(() => {
console.log("p3 - finally");
});
// p3 - catch: rejected called
// p3 - finally
Promise 코드예제
function asyncFunc(isSuccess) {
setTimeout(() => {
if (isSuccess) {
return { id: 13, name: "Silva" };
} else {
throw new Error("Failed !!");
}
}, 3000);
}
let result = asyncFunc(true);
console.log(result); // undefined
// 셋타임아웃의 맵 api에 3초뒤 실행되도록 스케쥴링 되었고,
// 논블로킹인 자바스크립트에서는 바로 코드가 실행되기 때문에
// result 안에 값이 할당되기 전에 실행되어 undefined를 반환하게 된다?
// Promise 사용해 개선
function asyncFuncProm(isSuccess) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (isSuccess) {
resolve({ id: 13, name: "silva" });
} else {
reject(new Error("Failed!!"));
}
}, 3000);
});
}
asyncFuncProm(true)
.then((result) => {
console.log(result);
})
.catch((error) => {
console.error(error);
});
promise chaining
new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1);
}, 1000);
}).then((result) => {
console.log("#1 resolve:", result);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(result * 10);
}, 1000);
}).then((result) => {
console.log("#2 resolve:", result);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(result * 10);
}, 1000);
}).then((result) => {
console.log("#3 resolve:", result);
});
});
});
// 1초 후
// #1 resolve: 1
// 1초 후
// #2 resolve: 10
// 1초 후
// #3 resolve: 100
Callback -> Promise -> async / await 로 발전
async / await 사용예제
function resolveAfter2Seconds(x) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(x);
}, 2000);
});
}
async function f1() {
var x = await resolveAfter2Seconds(10);
console.log(x); // 2초 뒤 10
}
f1();
async / await 간단한 용법
function fetchUser(isSuccess) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (isSuccess) {
resolve({
id: 1,
name: "홍길동",
gender: "male",
email: "bosv031999@gmail.com",
});
} else {
reject(new Error("유저정보 불러오기 싫패"));
}
}, 1000);
});
}
function fetchTodo(isSuccess) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (isSuccess) {
resolve({
userId: 1,
id: 1,
title: "우유 2개 사기",
completed: false,
});
} else {
reject(new Error("Todo정보 불러오기 실패"));
}
}, 1000);
});
}
async function getUserTodoData() {
try {
let user = await fetchUser(true);
// let user = await fetchUser(false);
console.log("유저정보: ", user);
let todo;
if (user.id === 1) {
// todo = await fetchTodo(true);
todo = await fetchTodo(false);
console.log("Todo 정보: ", todo); // 에러 반환
}
return {
userInfo: user,
todoInfo: todo,
};
} catch (error) {
console.log("에러가 발생했습니다.", error);
}
}
getUserTodoData().then((logData) => {
console.log(logData);
});