[Bun 系列]:了解这些 Web API,助力你开发 Bun 运行时应用(二)

一、简介

由于 Bun 是服务端运行时,DOM 等相关的 Web API 与其无关,无需实现。以下是 Web API 在 Bun 运行时中的实现,如果你对这些 API 还不是很熟悉,那么这篇文章对你应该很有用!

本文更加适合:对 Bun 感兴趣和对 Web 标准感兴趣的同学。

二、延迟

2.1) 结构图

2.2) 不太常用的 setTimeout 使用第三个参数

ts 复制代码
function call(name, greeting) {
  console.log(`${greeting}, ${name}!`);
}

setTimeout(sayHello, 1000, 'John', 'Hello'); // 1秒后执行,输出 "Hello, John!"

使用第三个参数,或者更多的参数时,与 call 类似 function.call(thisArg, arg1, arg2, ...)

三、定时器

3.1) 结构图

3.2) 传递第三个参数

ts 复制代码
function add(a, b) {
  console.log(`${a} + ${b} = ${a + b}`);
}

const intervalId = setInterval(add, 1000, 5, 3);

setTimeout(() => {
  clearInterval(intervalId); // 清除定时器
}, 5000); // 5秒后停止

四、加密

4.1) 结构图

web crypto 加密算法

4.3) 一个简单的 hash 加密 password 使用方法

以 digest 算法为例:

ts 复制代码
digest(
    algorithm: AlgorithmIdentifier,
    data: BufferSource,
  ): Promise<ArrayBuffer>;

需要将 password 编码为 bufferSource(Uint8Array 类型),然后在经过 digest 进行加密(此处是异步的),最后再将数据装换成 hashHex 16 进制数据:

ts 复制代码
// 使用 Web  API 进行密码哈希
async function hashPassword(password) {
  const encoder = new TextEncoder();
  const data = encoder.encode(password);
  const hashBuffer = await crypto.subtle.digest('SHA-256', data);
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  const hashHex = hashArray.map(byte => byte.toString(16).padStart(2, '0')).join('');
  return hashHex;
}

const password = 'your_password';

hashPassword(password)
  .then(hash => {
    console.log('哈希后的密码:', hash);
  })
  .catch(error => {
    console.error('哈希密码时出错:', error);
  });

五、调试

5.1) 调试结构图

  • console

5.2) 性能结构图

  • 加载时间
ts 复制代码
// 使用 Navigation Timing API 获取页面加载性能信息
const navigationTiming = window.performance.timing;
console.log('页面加载时间:', navigationTiming.loadEventEnd - navigationTiming.navigationStart, '毫秒');
  • 获取资源时间
ts 复制代码
// 使用 Resource Timing API 获取资源加载性能信息
const resourceEntries = performance.getEntriesByType('resource');
resourceEntries.forEach(entry => {
  console.log('资源 URL:', entry.name);
  console.log('资源加载时间:', entry.duration, '毫秒');
});

六、微任务栈

将一个微任务(microtask)异步地加入到执行队列中。微任务是在当前代码执行完毕后,但在下一个渲染或 I/O 事件之前执行的任务。这使得它们非常适合安排需要在当前代码执行后立即执行的任务,但又不想影响浏览器执行其他任务,比如渲染或处理用户输入。

ts 复制代码
console.log('开始');

// 微任务1:Promise
Promise.resolve().then(() => {
  console.log('微任务1 完成');
});

// 微任务2:process.nextTick(在 Node.js 中使用)
process.nextTick(() => {
  console.log('微任务2 完成');
});

// 微任务3:queueMicrotask
queueMicrotask(() => {
  console.log('微任务3 完成');
});

console.log('结束');

// 宏任务1:setTimeout
setTimeout(() => {
  console.log('宏任务1 完成');
}, 0);

console.log('最后');

七、错误

报告错误:reportError

ts 复制代码
const newError = new Error("Some error message");
global.reportError(newError);

八、用户交互

  • alert
ts 复制代码
alert("enter 回车, 退出交互")
  • prompt
ts 复制代码
const a = prompt('提示', '第二个参数') // 输出并打印
console.log(a)
  • confirm
ts 复制代码
const isMing = confirm('选择小明吗?') // 选择小明吗? [y/N] y
console.log(isMing) // 

与 web 端的逻辑基本上是一样的,但是没有真正的弹窗,提示,而是与终端进行交互。这个可能在写交互式命令行的时候特别有用。

九、Realms

9.1) ShadowRealms 类型

ts 复制代码
declare class Realm {
   constructor();
   importValue(specifier: string, bindingName: string): Promise<PrimitiveValueOrCallable>;
   evaluate(sourceText: string): PrimitiveValueOrCallable;
}

9.2) 简单示例

ts 复制代码
// 创建 Realm 对象
const myRealm = new Realm();

// 使用 importValue 方法导入值
myRealm.importValue('someSpecifier', 'someBindingName')
  .then((importedValue) => {
    console.log('导入的值:', importedValue);
  })
  .catch((error) => {
    console.error('导入值时发生错误:', error);
  });

// 使用 evaluate 方法评估代码
const sourceCode = 'const x = 10; x * 2;';
const result = myRealm.evaluate(sourceCode);
console.log('评估的结果:', result);

十、事件

10.1) 结构图

10.2) 自定义事件

ts 复制代码
const customEvent = new Event('customEvent');

global.addEventListener('customEvent', function(event) {
  console.log('自定义事件被触发了!');
});

// 触发自定义事件
global.dispatchEvent(customEvent);

注意:此处不是 document 对象,触发,而是 global 全局事件处理

10.3) 事件目标和自定事件组合

ts 复制代码
class MyEventTarget extends EventTarget {
  constructor(secret) {
    super();
    this._secret = secret;
  }

  get secret() {
    return this._secret;
  }

  updateSecret(newSecret) {
    const event = new CustomEvent("updateSecret", { detail: newSecret });
    this.dispatchEvent(event);
  }
}

const myEventTarget = new MyEventTarget(5);

// 添加事件监听器
myEventTarget.addEventListener("updateSecret", (e) => {
  myEventTarget._secret = e.detail;
});

const oldValue = myEventTarget.secret; // === 5
myEventTarget.updateSecret(7);
const newValue = myEventTarget.secret; // === 7

console.log(oldValue, newValue);

十一、小结

本文是继续讲解 Bun 中使用的 Web API 标准系列文章(一)的续补充,依然通过示例讲解常用 API 的用法,本文涉及了时间相关API,用户交互 API、加密算法,事件和调试等等。希望这篇文章能够帮助阅读的同学。

相关推荐
玩电脑的辣条哥3 小时前
Python如何播放本地音乐并在web页面播放
开发语言·前端·python
ew452183 小时前
ElementUI表格表头自定义添加checkbox,点击选中样式不生效
前端·javascript·elementui
suibian52353 小时前
AI时代:前端开发的职业发展路径拓宽
前端·人工智能
Moon.93 小时前
el-table的hasChildren不生效?子级没数据还显示箭头号?树形数据无法展开和收缩
前端·vue.js·html
垚垚 Securify 前沿站3 小时前
深入了解 AppScan 工具的使用:筑牢 Web 应用安全防线
运维·前端·网络·安全·web安全·系统安全
m0_748256144 小时前
SpringBoot
java·spring boot·后端
多想和从前一样5 小时前
Django 创建表时 “__str__ ”方法的使用
后端·python·django
工业甲酰苯胺6 小时前
Vue3 基础概念与环境搭建
前端·javascript·vue.js
涛粒子7 小时前
Spring Bean 生命周期的执行流程
java·后端·spring
mosquito_lover17 小时前
怎么把pyqt界面做的像web一样漂亮
前端·python·pyqt