This page was translated from English by the community. Learn more and join the MDN Web Docs community.

View in English Always switch to English

Promise.prototype.finally()

Baseline Widely available

This feature is well established and works across many devices and browser versions. Itโ€™s been available across browsers since โจ2018๋…„ 10์›”โฉ.

Promise ์ธ์Šคํ„ด์Šค์˜ finally() ๋ฉ”์„œ๋“œ๋Š” ํ”„๋กœ๋ฏธ์Šค๋ฅผ ์ฒ˜๋ฆฌํ•œ ํ›„(์ดํ–‰๋˜๊ฑฐ๋‚˜ ๊ฑฐ๋ถ€๋œ ํ›„) ํ˜ธ์ถœํ•  ํ•จ์ˆ˜๋ฅผ ์˜ˆ์•ฝํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” ์ฆ‰์‹œ ๋™๋“ฑํ•œ Promise ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ ํ”„๋กœ๋ฏธ์Šค ์ฒด์ด๋‹์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

finally() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด then() ์™€ catch() ์ฒ˜๋ฆฌ๊ธฐ ์† ์ฝ”๋“œ ์ค‘๋ณต์„ ํ”ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‹œ๋„ํ•ด ๋ณด๊ธฐ

function checkMail() {
  return new Promise((resolve, reject) => {
    if (Math.random() > 0.5) {
      resolve("Mail has arrived");
    } else {
      reject(new Error("Failed to arrive"));
    }
  });
}

checkMail()
  .then((mail) => {
    console.log(mail);
  })
  .catch((err) => {
    console.error(err);
  })
  .finally(() => {
    console.log("Experiment completed");
  });

๋ฌธ๋ฒ•

js
promiseInstance.finally(onFinally)

๋งค๊ฐœ๋ณ€์ˆ˜

onFinally

ํ”„๋กœ๋ฏธ์Šค๊ฐ€ ์ฒ˜๋ฆฌ๋œ ํ›„ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰๋  ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ๊ฑฐ๋ถ€๋œ ํ”„๋กœ๋ฏธ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๋Š” ์ด์ƒ ๋ฐ˜ํ™˜ ๊ฐ’์€ ๋ฌด์‹œ๋ฉ๋‹ˆ๋‹ค. ํ•จ์ˆ˜๋Š” ์ธ์ž ์—†์ด ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

๋ฐ˜ํ™˜ ๊ฐ’

๋ฐ˜ํ™˜ ๊ฐ’์€ ์ธ์Šคํ„ด์Šค์™€ ๋™์ผํ•œ Promise ์ž…๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์ฒ˜๋ฆฌ๊ธฐ์—์„œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฑฐ๋‚˜ ๊ฑฐ๋ถ€๋œ ํ”„๋กœ๋ฏธ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด, finally()๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ํ”„๋กœ๋ฏธ์Šค๋Š” ๋Œ€์‹  ๊ทธ ๊ฐ’์œผ๋กœ ๊ฑฐ๋ถ€๋ฉ๋‹ˆ๋‹ค. ์ด์™ธ์—๋Š” ์ฒ˜๋ฆฌ๊ธฐ์˜ ๋ฐ˜ํ™˜ ๊ฐ’์€ ์›๋ž˜ ํ”„๋กœ๋ฏธ์Šค์˜ ์ƒํƒœ์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์„ค๋ช…

finally() ๋ฉ”์„œ๋“œ๋Š” ๊ฒฐ๊ณผ์— ๊ด€๊ณ„์—†์ด ํ”„๋กœ๋ฏธ์Šค๊ฐ€ ์ฒ˜๋ฆฌ๋˜๊ณ  ๋‚˜์„œ ๋ฌด์–ธ๊ฐ€๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ฑฐ๋‚˜ ์ •๋ฆฌํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

finally() ๋ฉ”์„œ๋“œ๋Š” then(onFinally, onFinally) ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ๊ณผ ๋งค์šฐ ๋น„์Šทํ•˜์ง€๋งŒ ๋ช‡ ๊ฐ€์ง€ ์ฐจ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • ํ•จ์ˆ˜๋ฅผ ์ธ๋ผ์ธ์œผ๋กœ ๋งŒ๋“ค ๋•Œ, ๋‘ ๋ฒˆ ์„ ์–ธํ•˜๊ฑฐ๋‚˜ ๋ณ€์ˆ˜์— ํ• ๋‹นํ•  ํ•„์š” ์—†์ด ํ•œ ๋ฒˆ๋งŒ ์‚ฌ์šฉํ•ด์„œ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • onFinally ์ฝœ๋ฐฑ์€ ์ธ์ž๋ฅผ ๋ฐ›์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ดํ–‰๋œ ๊ฐ’ ํ˜น์€ ๊ฑฐ๋ถ€๋œ ์ด์œ ์™€ ๋ฌด๊ด€ํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ์‹คํ–‰๋˜๋ฏ€๋กœ ์ธ์ž๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • finally() ํ˜ธ์ถœ์€ ๋ณดํ†ต ์™ธ๋ถ€์˜ ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š์œผ๋ฉฐ ์›๋ž˜ ํ”„๋กœ๋ฏธ์Šค์˜ ์ตœ์ข… ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ์˜ˆ์‹œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.
    • Promise.resolve(2).then(() => 77, () => {}) ๋Š” 77๋กœ ์ดํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด์™€๋Š” ๋‹ค๋ฅด๊ฒŒ, Promise.resolve(2).finally(() => 77) ๋Š” 2๋กœ ์ดํ–‰๋ฉ๋‹ˆ๋‹ค.
    • ์œ ์‚ฌํ•˜๊ฒŒ Promise.reject(3).then(() => {}, () => 88) ๋Š” 88๋กœ ๊ฑฐ๋ถ€๋ฉ๋‹ˆ๋‹ค. ์ด์™€๋Š” ๋‹ฌ๋ฆฌ Promise.reject(3).finally(() => {}) ๋Š” 3๋กœ ๊ฑฐ๋ถ€๋ฉ๋‹ˆ๋‹ค.

์ฐธ๊ณ : finally ์ฝœ๋ฐฑ ๋‚ด ์˜ˆ์™ธ ๋ฐœ์ƒ ๋˜๋Š” ๊ฑฐ๋ถ€๋œ ํ”„๋กœ๋ฏธ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ๊ฑฐ๋ถ€๋œ ํ”„๋กœ๋ฏธ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด Promise.reject(3).finally(() => { throw 99; }) ์™€ Promise.reject(3).finally(() => Promise.reject(99)) ๋Š” ๋ชจ๋‘ 99๋กœ ๊ฑฐ๋ถ€๋œ ํ”„๋กœ๋ฏธ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

catch()์ฒ˜๋Ÿผ , finally()๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ ์ž์‹ ์„ ํ˜ธ์ถœํ•œ ๊ฐ์ฒด์˜ then ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. onFinally๊ฐ€ ํ•จ์ˆ˜๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ, then()์€ ๋‘ ์ธ์ž ๋ชจ๋‘ onFinally๋กœ ๋„˜์–ด๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉฐ, ์ฆ‰ Promise.prototype.then()์—๊ฒŒ ์œ ์šฉํ•œ ์ฒ˜๋ฆฌ๊ธฐ๊ฐ€ ํฌํ•จ๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. ๊ทธ ์™ธ์˜ ๊ฒฝ์šฐ then()์€ ๋‚ด๋ถ€์ ์œผ๋กœ ์ƒ์„ฑ๋œ ๋‘ ๊ฐœ์˜ ํ•จ์ˆ˜์™€ ํ•จ๊ป˜ ํ˜ธ์ถœ๋˜๋ฉฐ, ๋‹ค์Œ๊ณผ ๋น„์Šทํ•˜๊ฒŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

๊ฒฝ๊ณ  : ๋‹ค์Œ์€ ์„ค๋ช…์„ ์œ„ํ•œ ์˜ˆ์‹œ์ด๋ฉฐ ์‹ค์ œ ํด๋ฆฌํ•„์ด ์•„๋‹™๋‹ˆ๋‹ค.

js
promise.then(
  (value) => Promise.resolve(onFinally()).then(() => value),
  (reason) =>
    Promise.resolve(onFinally()).then(() => {
      throw reason;
    }),
);

finally() ๋ฉ”์„œ๋“œ๊ฐ€ then() ์„ ํ˜ธ์ถœํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋ธŒํด๋ž˜์‹ฑ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์œ„ ์˜ˆ์‹œ์˜ Promise.resolve() ํ˜ธ์ถœ์„ ์ฃผ๋ชฉํ•˜์„ธ์š”. ์‹ค์ œ๋กœ onFinally() ์˜ ๋ฐ˜ํ™˜ ๊ฐ’์€ Promise.resolve() ์™€ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ์ดํ–‰๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ดํ–‰๋œ ํ”„๋กœ๋ฏธ์Šค์˜ ์ง„์งœ ์ƒ์„ฑ์ž๋Š” ์„œ๋ธŒํด๋ž˜์Šค๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. finally() ๋Š” ์ด ์ƒ์„ฑ์ž๋ฅผ promise.constructor[@@species] ์—์„œ ์–ป์Šต๋‹ˆ๋‹ค.

์˜ˆ์‹œ

finally() ์‚ฌ์šฉํ•˜๊ธฐ

js
let isLoading = true;

fetch(myRequest)
  .then((response) => {
    const contentType = response.headers.get("content-type");
    if (contentType && contentType.includes("application/json")) {
      return response.json();
    }
    throw new TypeError("Oops, we haven't got JSON!");
  })
  .then((json) => {
    /* JSON ์ฒ˜๋ฆฌ */
  })
  .catch((error) => {
    console.error(error); // ์ด ์ค„๋„ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (์˜ˆ: console = {})
  })
  .finally(() => {
    isLoading = false;
  });

๋ช…์„ธ์„œ

Specification
ECMAScriptยฎ 2026 Language Specification
# sec-promise.prototype.finally

๋ธŒ๋ผ์šฐ์ € ํ˜ธํ™˜์„ฑ

๊ฐ™์ด ๋ณด๊ธฐ