λλ¦Όμ½λ© by μ리, https://www.youtube.com/watch?v=s1vpVCrT8f4
javascript.info, https://ko.javascript.info/promise-basics
MDN, https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise
μ°Έκ³ μ¬μ΄νΈμ λ΄μ©μ κ°μΈμ μΌλ‘ 볡μ΅νκΈ° νΈνλλ‘ μ¬κ΅¬μ±ν κΈμ λλ€.
μμΈν μ€λͺ μ μ°Έκ³ μ¬μ΄νΈλ₯Ό μ΄ν΄λ³΄μκΈ° λ°λλλ€.
κΈ°μ‘΄μ λΉλκΈ° μ²λ¦¬λ λΉλκΈ° ν¨μμ μ½λ°± ν¨μλ₯Ό μ λ¬νλ λ°©μμΌλ‘ ν΄κ²°νμ΅λλ€.
νμ§λ§ λΉλκΈ° λμμ ν΄μΌν μΌμ΄ λ§μμ§κ³ κ·Έ μμλ₯Ό 보μ₯νκΈ° μν΄μ μ½λ°± ν¨μλ₯Ό μΈμλ‘ λ°λ ν¨μλ€μ μ€μ²©ν΄μ μ¬μ©νλ€λ³΄λ μ½λ°± μ§μ₯μ΄ λ°μνκ² λκ³ μ΄λ κ°λ
μ±μ΄ λ¨μ΄μ§κ³ μ μ§λ³΄μλ₯Ό μ΄λ ΅κ² λ§λ€μμ΅λλ€. μ΄λ₯Ό 보μνκ³ μ λ±μ₯ν κ²μ΄ Promise
μ
λλ€.
μλλ μ½λ°± μ§μ₯μ λν μμμ λλ€.
class UserStorage {
loginUser(id, password, onSuccess, onError) {
setTimeout(() => {
if (
(id === "Tomas" && password === "1234") ||
(id === "James" && password === "5678")
) {
onSuccess(id);
} else {
onError(new Error("Not Found"));
}
}, 2000);
}
getRoles(user, onSuccess, onError) {
setTimeout(() => {
if (user === "Tomas") {
onSuccess({ name: "Tomas", role: "admin" });
} else {
onError(new Error("No Access"));
}
}, 1000);
}
}
const userStorage = new UserStorage();
const id = prompt("Enter your id");
const password = prompt("Enter your password");
userStorage.loginUser(
id,
password,
(user) => {
userStorage.getRoles(
user,
(userWithRole) =>
alert(`Hello! ${userWithRole.name}. You have a ${userWithRole.role}`),
(error) => console.log(error)
);
},
(error) => console.log(error)
);
μ¬μ©μλ‘λΆν° id
μ password
λ₯Ό μ
λ ₯ λ°μμ μ μ μΈμ§ νμΈνκ³ μ μ id
λ₯Ό ν΅ν΄ κΆνμ λΆμ¬νλ μ½λμ
λλ€. μ½λ°± ν¨μλ₯Ό μΈμλ‘ λ°λ λΉλκΈ° ν¨μμ μ€μ²©μ΄ λ λ²λ°μ μκΈ°μ§ μμμ§λ§ λ§€μ° κ°λ
μ±μ΄ λ¨μ΄μ§κ³ μ μ§λ³΄μκ° μ΄λ €μμ§λλ€.
Promise
λ μλ°μ€ν¬λ¦½νΈμ κ°μ²΄λ‘ λΉλκΈ° μ²λ¦¬λ₯Ό μν΄ μ¬μ©λ©λλ€. μλμ κ°μ΄ μμ±ν μ μμ΅λλ€.
const promise = new Promise(function (resolve, reject) {
// executor
console.log('Doing something...(Network, Read files)');
});
// κ°μ²΄ μμ± μκ° λ°λ‘ μ€νλ¨
>> Doing something...(Network, Read files)
new Promise()
μ μ λ¬λλ ν¨μλ executor()
(μ€νμ, μ€ν ν¨μ)λΌκ³ λΆλ¦
λλ€. executor()
λ new Promise()
κ° λ§λ€μ΄μ§ λ μλμΌλ‘ μ€νλ©λλ€.
executor()
μ μΈμ resolve()
μ reject()
λ μλ°μ€ν¬λ¦½νΈμμ μ체 μ 곡νλ μ½λ°±μ
λλ€. κ°λ°μλ resolve()
μ reject()
λ₯Ό μ κ²½ μ°μ§ μκ³ executor()
μ μ½λλ§ μμ±νλ©΄ λ©λλ€.
λμ executor()
μμ κ²°κ³Όλ₯Ό μ¦μ μ»λ λ¦κ² μ»λ μκ΄μμ΄ μν©μ λ°λΌ μΈμλ‘ λκ²¨μ€ μ½λ°± μ€ νλλ₯Ό λ°λμ νΈμΆν΄μΌ ν©λλ€.
resolve(value)
μΌμ΄ μ±κ³΅μ μΌλ‘ λλ κ²½μ° κ·Έ κ²°κ³Όλ₯Ό λνλ΄λvalue
μ ν¨κ» νΈμΆ
reject(error)
μλ¬ λ°μ μ μλ¬ κ°μ²΄λ₯Ό λνλ΄λerror
μ ν¨κ» νΈμΆ
μμ½νλ©΄ λ€μκ³Ό κ°μ΅λλ€. executor()
λ μλμΌλ‘ μ€νλλλ° μ¬κΈ°μ μνλ μΌμ΄ μ²λ¦¬λ©λλ€. μ²λ¦¬κ° λλλ©΄ executor()
λ μ²λ¦¬ μ±κ³΅ μ¬λΆμ λ°λΌ resolve()
λ reject()
λ₯Ό νΈμΆν©λλ€.
ννΈ, new Promise()
μμ±μκ° λ°ννλ promise
κ°μ²΄λ λ€μκ³Ό κ°μ λ΄λΆ νλ‘νΌν°λ₯Ό κ°μ΅λλ€.
state
μ²μμpending
μ΄μλ€κ°resolve()
κ° νΈμΆλλ©΄fulfilled
,reject
κ° νΈμΆλλ©΄rejected
λ‘ λ³ν©λλ€.
result
μ²μμundefined
μ΄μλ€κ°resolve(value)
κ° νΈμΆλλ©΄value
λ‘,reject(error)
κ° νΈμΆλλ©΄error
λ‘ λ³ν©λλ€.
λ°λΌμ executor()
λ μλ κ·Έλ¦Όκ³Ό κ°μ΄ promise
μ μνλ₯Ό λ μ€ νλλ‘ λ³νμν΅λλ€.
const promise = new Promise(function(resolve, reject) {
// νλΌλ―Έμ€κ° λ§λ€μ΄μ§λ©΄ executor ν¨μλ μλμΌλ‘ μ€νλ©λλ€.
// 1μ΄ λ€μ μΌμ΄ μ±κ³΅μ μΌλ‘ λλ¬λ€λ μ νΈκ° μ λ¬λλ©΄μ resultλ 'done'μ΄ λ©λλ€.
setTimeout(() => resolve("done"), 1000);
});
const promise = new Promise(function(resolve, reject) {
// 1μ΄ λ€μ μλ¬μ ν¨κ» μ€νμ΄ μ’
λ£λμλ€λ μ νΈλ₯Ό 보λ
λλ€.
setTimeout(() => reject(new Error("μλ¬ λ°μ!")), 1000);
});
π₯ νλΌλ―Έμ€λ μ±κ³΅ λλ μ€ν¨λ§ ν©λλ€.
executor()
λ resolve()
λ reject()
μ€ νλλ₯Ό λ°λμ νΈμΆν΄μΌ ν©λλ€. μ΄λ λ³κ²½λ μνλ λ μ΄μ λ³νμ§ μμ΅λλ€. μ²λ¦¬κ° λλ νλΌλ―Έμ€μ resolveμ rejectλ₯Ό νΈμΆνλ©΄ 무μλ©λλ€.
const promise = new Promise(function(resolve, reject) {
resolve("done");
reject(new Error("β¦")); // 무μλ¨
setTimeout(() => resolve("β¦")); // 무μλ¨
});
μ΄λ κ² executor()
μ μν΄ μ²λ¦¬κ° λλ μΌμ κ²°κ³Ό νΉμ μλ¬λ§ κ°μ§ μ μμ΅λλ€.
μ¬κΈ°μ λνμ¬ resolve()
λ reject()
λ μΈμλ₯Ό νλλ§ λ°κ³ (νΉμ μ무κ²λ λ°μ§ μμ) κ·Έ μ΄μΈμ μΈμλ 무μνλ€λ νΉμ±λ μμ΅λλ€.
then()
μ νλΌλ―Έμ€μμ κ°μ₯ μ€μνκ³ κΈ°λ³Έμ΄ λλ λ©μλμ
λλ€.
λ¬Έλ²μ λ€μκ³Ό κ°μ΅λλ€.
promise.then(
function(result) { /* κ²°κ³Ό(result)λ₯Ό λ€λ£Ήλλ€ */ },
function(error) { /* μλ¬(error)λ₯Ό λ€λ£Ήλλ€ */ }
);
then()
μ 첫 λ²μ§Έ μΈμλ νλΌλ―Έμ€κ° μ΄νλμμ λ μ€νλλ ν¨μμ΄κ³ , μ¬κΈ°μ μ€ν κ²°κ³Όλ₯Ό λ°μ΅λλ€.
then()
μ λ λ²μ§Έ μΈμλ νλΌλ―Έμ€κ° κ±°λΆλμμ λ μ€νλλ ν¨μμ΄κ³ , μ¬κΈ°μ μλ¬λ₯Ό λ°μ΅λλ€.
μλ μμλ μ±κ³΅μ μΌλ‘ μ΄νλ νλΌλ―Έμ€μ μ΄λ»κ² λ°μνλμ§ λ³΄μ¬μ€λλ€.
const promise = new Promise(function(resolve, reject) {
setTimeout(() => resolve("done!"), 1000);
});
// resolve ν¨μλ .thenμ 첫 λ²μ§Έ ν¨μ(μΈμ)λ₯Ό μ€νν©λλ€.
promise.then(
result => alert(result), // 1μ΄ ν "done!"μ μΆλ ₯
error => alert(error) // μ€νλμ§ μμ
);
첫 λ²μ§Έ ν¨μκ° μ€νλμμ΅λλ€.
νλΌλ―Έμ€κ° κ±°λΆλ κ²½μ°μλ μλμ κ°μ΄ λ λ²μ§Έ ν¨μκ° μ€νλ©λλ€.
const promise = new Promise(function(resolve, reject) {
setTimeout(() => reject(new Error("μλ¬ λ°μ!")), 1000);
});
// reject ν¨μλ .thenμ λ λ²μ§Έ ν¨μλ₯Ό μ€νν©λλ€.
promise.then(
result => alert(result), // μ€νλμ§ μμ
error => alert(error) // 1μ΄ ν "Error: μλ¬ λ°μ!"λ₯Ό μΆλ ₯
);
μμ
μ΄ μ±κ³΅μ μΌλ‘ μ²λ¦¬λ κ²½μ°λ§ λ€λ£¨κ³ μΆλ€λ©΄ then()
μ μΈμλ₯Ό νλλ§ μ λ¬νλ©΄ λ©λλ€.
const promise = new Promise(resolve => {
setTimeout(() => resolve("done!"), 1000);
});
promise.then(result => alert(result)); // 1μ΄ λ€ "done!" μΆλ ₯
// promise.then(alert); μΆμ½ νν
μλ¬κ° λ°μν κ²½μ°λ§ λ€λ£¨κ³ μΆλ€λ©΄ then(null, errorHandlingFunction)
κ³Ό κ°μ΄ null
μ 첫 λ²μ§Έ μΈμλ‘ μ λ¬νλ©΄ λ©λλ€. catch(errorHandlingFunction)
λ₯Ό μ¨λ λλλ°, catch()
λ then()
μ null
μ μ λ¬νλ κ²κ³Ό λμΌνκ² μλν©λλ€.
const promise = new Promise((resolve, reject) => {
setTimeout(() => reject(new Error("μλ¬ λ°μ!")), 1000);
});
// .catch(f)λ promise.then(null, f)κ³Ό λμΌνκ² μλν©λλ€
promise.catch(error => alert(error));
// promise.catch(alert); μΆμ½ νν
catch(f)
λ λ¬Έλ²μ΄ κ°κ²°νλ€λ μ λ§ λΉΌκ³ then(null, f)
κ³Ό μλ²½νκ² κ°μ΅λλ€.
try {...} catch {...}
μ finally {...}
μ μ΄ μλ κ²μ²λΌ, νλΌλ―Έμ€μλ finally()
κ° μμ΅λλ€.
νλΌλ―Έμ€κ° μ²λ¦¬λλ©΄(μ΄νμ΄λ κ±°λΆ) f
κ° νμ μ€νλλ€λ μ μμ finally(f)
νΈμΆμ then(f, f)
κ³Ό μ μ¬ν©λλ€.
μΈλͺ¨κ° μμ΄μ§ λ‘λ© μΈλμΌμ΄ν°(loading indicator)λ₯Ό λ©μΆλ κ²½μ°κ°μ΄, κ²°κ³Όκ° μ΄λ»λ λ§λ¬΄λ¦¬κ° νμνλ©΄ finally()
κ° μ μ©ν©λλ€.
κ·Έλ°λ° finally()
λ then(f, f)
κ³Ό μμ ν κ°μ§ μμ΅λλ€. μ°¨μ΄μ μ λ€μκ³Ό κ°μ΅λλ€.
finally()
νΈλ€λ¬μ μΈμκ° μμ΅λλ€. finally()
μμ νλΌλ―Έμ€κ° μ΄νλμλμ§, κ±°λΆλμλμ§ μ μ μμ΅λλ€. finally()
μμ μ μ°¨λ₯Ό λ§λ¬΄λ¦¬νλ λμμ μννκΈ° λλ¬Έμ μ±κ³΅Β·μ€ν¨ μ¬λΆλ₯Ό λͺ°λΌλ λ©λλ€.
finally()
νΈλ€λ¬λ μλμΌλ‘ λ€μ νΈλ€λ¬μ κ²°κ³Όμ μλ¬λ₯Ό μ λ¬ν©λλ€.
result
κ° finally()
λ₯Ό κ±°μ³ then()
κΉμ§ μ λ¬λλ κ²μ νμΈν΄λ΄
μλ€.
new Promise((resolve, reject) => {
setTimeout(() => resolve("κ²°κ³Ό"), 2000)
})
.finally(() => alert("νλΌλ―Έμ€κ° μ€λΉλμμ΅λλ€."))
.then(result => alert(result)); // <-- .thenμμ resultλ₯Ό λ€λ£° μ μμ
νλΌλ―Έμ€μμ μλ¬κ° λ°μνκ³ μ΄ μλ¬κ° finally()
λ₯Ό κ±°μ³ catch()
κΉμ§ μ λ¬λλ κ²μ νμΈν΄λ΄
μλ€.
new Promise((resolve, reject) => {
throw new Error("μλ¬ λ°μ!");
})
.finally(() => alert("νλΌλ―Έμ€κ° μ€λΉλμμ΅λλ€."))
.catch(err => alert(err)); // <-- .catchμμ μλ¬ κ°μ²΄λ₯Ό λ€λ£° μ μμ
finally()
λ νλΌλ―Έμ€ κ²°κ³Όλ₯Ό μ²λ¦¬νκΈ° μν΄ λ§λ€μ΄ μ§ κ² μλλλ€. νλΌλ―Έμ€ κ²°κ³Όλ finally()
λ₯Ό ν΅κ³Όν΄μ μ λ¬λ©λλ€. μ΄λ° νΉμ§μ μμ£Ό μ μ©νκ² μ¬μ©λκΈ°λ ν©λλ€.
finally(f)
λ ν¨μ f
λ₯Ό μ€λ³΅ν΄μ μΈ νμκ° μκΈ° λλ¬Έμ then(f, f)
λ³΄λ€ λ¬Έλ² μΈ‘λ©΄μμ λ νΈλ¦¬ν©λλ€.