为了账号安全,请及时绑定邮箱和手机立即绑定

阻止错误在阻止你之前出现

防止错误阻止你:安全赋值运算符 (?=) 和优雅处理承诺

随着JavaScript的发展,新的特性和提案不断涌现,旨在提高编码效率并减少错误。其中一个特性是安全赋值运算符?=),这是语言的一个提议新增功能。虽然我们仍在等待其正式发布,但我们今天可以实现类似的功能,以保护我们的代码免受诸如nullundefined值等常见问题的影响。

在本文中,我们将探讨 ?= 操作符,使用现有的JavaScript构建自己的版本,并介绍在异步操作中更优雅地处理承诺的实用方法。

了解安全赋值操作符 (?=)

?= 操作符是什么?

安全赋值操作符 (?=) 允许开发人员仅在目标为 nullundefined 时将值赋给变量。这是一种更简洁的方式来表达,“如果变量为空,则赋值。”

这里的工作原理是:

    let 用户名 = null;
    用户名 ?= "Shahar"; 
    console.log(用户名); // 输出: "Shahar"

进入全屏模式 退出全屏模式

在这种情况下,变量 username 被赋值为 "Shahar",因为它的值原来是 null。如果 username 已经有值了,该操作符就会跳过赋值。

为什么它很有用

?=运算符通过减少显式的if检查或三元运算符的使用,来简化代码,从而确保安全赋值。然而,此运算符在ECMAScript中仍处于提案阶段,这意味着在成为JavaScript语言的一部分之前它可能会发生变化。你可以在这里跟踪其发展情况:这里

构建一个安全赋值函数

推出 safeAssign

在等待 ?= 成为官方标准的同时,我们可以通过一个自定义的辅助函数 safeAssign 来模仿它的行为。这个函数使用了空值合并运算符 (??),该运算符已经在现代环境中得到了广泛支持。

这里是我们的 safeAssign 函数:

    function safeAssign(target, value) {
      return target ?? value;
    }
    

进入全屏模式 退出全屏模式

示例演示

让我们看看它是如何工作的:

    let username = undefined;
    username = safeAssign(username, "Shahar");
    console.log(username); // 输出: "Shahar"

进入全屏模式 退出全屏模式

这实际上就是 ?= 操作符的作用。如果变量为 nullundefined,我们就给它赋值;否则,我们就保持原样不作改动。

safeAssign 的限制

虽然 safeAssign 提供了与 ?= 类似的功能,但它存在一些限制:

  • 简洁性 : safeAssign 是一个工具函数,无法提供与原生 ?= 操作符相同的语法优雅程度。过度使用自定义函数可能导致代码更加冗长。
  • 性能 : 虽然在小型应用中 safeAssign 的性能影响可以忽略不计,但在大型系统中,由于引擎优化,原生操作符如 ?= 可能会更快。
  • 浏览器支持 : safeAssign 中使用的空值合并操作符 (??) 在大多数现代浏览器和环境中得到支持,但在较旧的环境中可能需要使用 polyfills 才能支持。

与其他语言的快速比较

许多其他语言提供了与提议的 ?= 操作符类似的功能:

  • C# 有一个空合并赋值运算符 (??=),其行为类似于 JavaScript 的 ?= 提案。
  • Python 使用 or 关键字进行安全赋值,其中 a = a or value 是一种常见的模式,用于仅在 a 为假值时赋值。

这些操作符使得处理可能为空的值更加直接,减少了冗余代码。

使用 safeAwait 处理异步操作

介绍 safeAwait

在使用JavaScript进行异步操作时,很容易遇到被拒绝的Promise或意外的结果。与其使用.catch()手动处理每个拒绝,我们可以使用一个名为safeAwait的自定义函数来简化这一过程,该函数将Promise包裹在一个更干净、更安全的结构中。

这里是 safeAwait 函数:

    async function safeAwait(promise, errorHandler) {
      try {
        const data = await promise;
        return [null, data]; // 成功:没有错误,返回数据
      } catch (error) {
        if (errorHandler) errorHandler(error); // 可选错误处理程序
        return [error, null]; // 发生错误,返回错误和空数据
      }
    }
    

进入全屏模式 退出全屏模式

示例:带有错误处理的数据获取

让我们使用 safeAwait 从API获取数据并处理可能出现的错误:

    async function 获取数据() {
      const [错误, 响应] = await safeAwait(
        fetch("https://api.example.com"),
        (err) => console.error("请求失败:", err)
      );
    
      if (错误) return; // 如果有错误则退出
      return 响应; // 如果成功则返回响应
    }
    

进入全屏模式 退出全屏模式

在这个例子中,safeAwait 处理了成功和错误两种情况,使得调用函数能够以更可预测的方式处理结果。

safeAwait 的变体

我们也可以为 safeAwait 扩展不同的用例。例如,这里有一个版本会在失败前重试一次承诺:

    async function safeAwaitWithRetry(promise, errorHandler, retries = 1) {
      let attempt = 0;
      while (attempt <= retries) {
        const [error, data] = await safeAwait(promise, errorHandler);
        if (!error) return [null, data];
        attempt++;
      }
      return [new Error("达到最大重试次数"), null];
    }
    

进入全屏模式 退出全屏模式

这种变体在放弃之前会重试指定次数。

JavaScript 中的最佳错误处理实践

当处理异步代码时,正确的错误处理至关重要。这里有一些最佳实践:

  1. 始终处理被拒绝的承诺:未处理的被拒绝承诺可能导致崩溃或未定义的行为。使用 try/catch.catch() 确保承诺得到妥善处理。
  2. 集中错误处理:使用 safeAwait 这样的工具函数可以让你集中处理错误,使管理和调试代码变得更加容易。
  3. 优雅降级:确保你的应用程序能够优雅地从错误中恢复,而不会崩溃或让用户处于未定义的状态。
  4. 使用自定义错误消息:在抛出错误时,提供有意义的错误消息以帮助调试。

使用 safeAssignsafeAwait 之前的和之后的代码对比

这里快速比较了这些工具如何清理你的代码。

未使用 safeAssign:

    如果 (user === null || user === undefined) {
      user = "Shahar";
    }
    

进入全屏模式 退出全屏模式

使用 safeAssign:

    user = safeAssign(user, "Shahar");

进入全屏模式 退出全屏模式

未使用 safeAwait:

    try {
      const response = await fetch("https://api.example.com");
    } catch (error) {
      console.error("请求失败:", error);
    }
    

进入全屏模式 退出全屏模式

使用 safeAwait

    const [error, response] = await safeAwait(fetch("https://api.example.com"), (err) => console.error("请求失败:", err));

进入全屏模式 退出全屏模式

结论

总之,虽然安全赋值运算符 (?=) 仍然是一个提案,但我们今天可以使用 safeAssign 函数为 nullish 值赋值,并使用 safeAwait 处理更复杂的异步操作。这两个工具简化了你的代码,使其更易读和更易维护。

主要收获:

  • ?= 操作符简化了安全赋值,但目前仍处于提案阶段。
  • 可以使用空值合并操作符 (??) 来通过 safeAssign 复现 ?= 的功能,该操作符已被广泛支持。
  • 对于异步操作,safeAwait 提供了一种更干净的方式来处理 promise 的拒绝和错误。
  • 关注 ECMAScript 提案 以获取未来的更新。

通过利用这些模式,你可以像专业人士一样处理错误,并保持代码整洁、易读且安全。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消