本页内容

程序生命周期

Deno 支持浏览器兼容的生命周期事件

  • load: 当整个页面加载完毕(包括所有依赖资源,如样式表和图像)时触发。
  • beforeunload: 当事件循环没有更多工作要做并且即将退出时触发。调度更多异步工作(如计时器或网络请求)将导致程序继续运行。
  • unload: 当文档或子资源正在卸载时触发。
  • unhandledrejection: 当一个没有拒绝处理程序的 Promise 被拒绝时触发,即一个没有 .catch() 处理程序或 .then() 的第二个参数的 Promise。
  • rejectionhandled: 当一个 .catch() 处理程序被添加到一个已经拒绝的 Promise 时触发。此事件仅在安装了 unhandledrejection 监听器以阻止事件传播(这将导致程序以错误终止)时触发。

您可以使用这些事件在程序中提供设置和清理代码。

load 事件的监听器可以是异步的,并且将被等待,此事件无法取消。beforeunload 的监听器需要是同步的,并且可以取消以使程序继续运行。unload 事件的监听器需要是同步的,并且无法取消。

示例 跳转到标题

main.ts

import "./imported.ts";

const handler = (e: Event): void => {
  console.log(`got ${e.type} event in event handler (main)`);
};

globalThis.addEventListener("load", handler);

globalThis.addEventListener("beforeunload", handler);

globalThis.addEventListener("unload", handler);

globalThis.onload = (e: Event): void => {
  console.log(`got ${e.type} event in onload function (main)`);
};

globalThis.onbeforeunload = (e: Event): void => {
  console.log(`got ${e.type} event in onbeforeunload function (main)`);
};

globalThis.onunload = (e: Event): void => {
  console.log(`got ${e.type} event in onunload function (main)`);
};

console.log("log from main script");

imported.ts

const handler = (e: Event): void => {
  console.log(`got ${e.type} event in event handler (imported)`);
};

globalThis.addEventListener("load", handler);
globalThis.addEventListener("beforeunload", handler);
globalThis.addEventListener("unload", handler);

globalThis.onload = (e: Event): void => {
  console.log(`got ${e.type} event in onload function (imported)`);
};

globalThis.onbeforeunload = (e: Event): void => {
  console.log(`got ${e.type} event in onbeforeunload function (imported)`);
};

globalThis.onunload = (e: Event): void => {
  console.log(`got ${e.type} event in onunload function (imported)`);
};

console.log("log from imported script");

关于此示例的几点说明

  • addEventListeneronload/onunload 都有 globalThis 前缀,但您也可以使用 self 或不使用任何前缀。 不建议使用 window 作为前缀.
  • 您可以使用 addEventListener 和/或 onload/onunload 来定义事件处理程序。它们之间存在重大差异,让我们运行示例
$ deno run main.ts
log from imported script
log from main script
got load event in event handler (imported)
got load event in event handler (main)
got load event in onload function (main)
got onbeforeunload event in event handler (imported)
got onbeforeunload event in event handler (main)
got onbeforeunload event in onbeforeunload function (main)
got unload event in event handler (imported)
got unload event in event handler (main)
got unload event in onunload function (main)

所有使用 addEventListener 添加的监听器都已运行,但 main.ts 中定义的 onloadonbeforeunloadonunload 覆盖了 imported.ts 中定义的处理程序。

换句话说,您可以使用 addEventListener 注册多个 "load""unload" 事件处理程序,但只会执行最后定义的 onloadonbeforeunloadonunload 事件处理程序。出于这个原因,最好在可能的情况下使用 addEventListener

beforeunload 示例 跳转到标题

// beforeunload.js
let count = 0;

console.log(count);

globalThis.addEventListener("beforeunload", (e) => {
  console.log("About to exit...");
  if (count < 4) {
    e.preventDefault();
    console.log("Scheduling more work...");
    setTimeout(() => {
      console.log(count);
    }, 100);
  }

  count++;
});

globalThis.addEventListener("unload", (e) => {
  console.log("Exiting");
});

count++;
console.log(count);

setTimeout(() => {
  count++;
  console.log(count);
}, 100);

运行此程序将打印

$ deno run beforeunload.js
0
1
2
About to exit...
Scheduling more work...
3
About to exit...
Scheduling more work...
4
About to exit...
Exiting

这使我们能够在 Node 兼容性层中填充 process.on("beforeExit")

unhandledrejection 事件示例: 跳转到标题

此版本添加了对 unhandledrejection 事件的支持。当一个没有拒绝处理程序的 Promise 被拒绝时,会触发此事件,即一个没有 .catch() 处理程序或 .then() 的第二个参数的 Promise。

// unhandledrejection.js
globalThis.addEventListener("unhandledrejection", (e) => {
  console.log("unhandled rejection at:", e.promise, "reason:", e.reason);
  e.preventDefault();
});

function Foo() {
  this.bar = Promise.reject(new Error("bar not available"));
}

new Foo();
Promise.reject();

运行此程序将打印

$ deno run unhandledrejection.js
unhandled rejection at: Promise {
  <rejected> Error: bar not available
    at new Foo (file:///dev/unhandled_rejection.js:7:29)
    at file:///dev/unhandled_rejection.js:10:1
} reason: Error: bar not available
    at new Foo (file:///dev/unhandled_rejection.js:7:29)
    at file:///dev/unhandled_rejection.js:10:1
unhandled rejection at: Promise { <rejected> undefined } reason: undefined

此 API 将使我们能够在将来的版本中在 Node 兼容性层中填充 process.on("unhandledRejection")