在现代 JavaScript 中如何安全获取网络数据

在现代 JavaScript 中如何安全获取网络数据,在 JavaScript 中fetch非常棒。,但是,您的代码中可能会散布着这样的内容:,这段代码虽然简单易用,但存在许多问题。,你可以说“哦,是的,错误处理”,然后像这样重写它:,当然,这是一个改进,但仍然存在问题。,在这里,我们假设 user 实际上是一个用户对象……但这假设我们得到了 200 响应。,但 fetch 不会针对非 200 状态抛出错误,因此您实际上可能收到 400(错误请求)、401(未授权)、404(未找到)、500(内部服务器错误)或各种其他问题 .,因此,我们可以进行另一个更新:,现在,我们终于很好地使用了 fetch。 但这可能有点笨拙,因为每次都必须记住,而且你必须希望你团队中的每个人每次都能处理这些情况。,它在控制流方面也不是最优雅的。 在可读性方面,我个人更喜欢本文开头的有问题的代码。 它读起来很干净——获取用户,解析为 json,用用户对象做事。,但在这种格式中,我们获取用户、处理一堆错误情况、解析 json、处理其他错误情况等。这有点不和谐,尤其是此时我们在业务逻辑之上和之下都有错误处理,而不是 集中在一个地方。,如果请求有问题,一个更优雅的解决方案可能是抛出异常,而不是在多个地方处理错误:,但是我们还有最后一个问题——当需要处理错误时,我们丢失了很多有用的上下文。 我们实际上无法访问 catch 块中的 res,因此在处理错误时我们实际上并不知道响应的状态代码或主体是什么。,这将使我们很难知道要采取的最佳措施,并给我们留下非常无用的日志。,此处改进的解决方案可能是创建您自己的自定义错误类,您可以在其中转发响应详细信息:,现在,当我们保留状态代码时,我们可以更智能地处理错误。,例如,我们可以在 500 上提醒用户我们遇到了问题,并可能重试或联系我们的支持。,或者如果状态为 401,他们当前未授权,可能需要重新登录等。,我有一个关于我们最新最好的解决方案,最后一个问题——它仍需要开发人员每次都编写一些像样的样板文件。 在整个项目范围内进行更改,或强制使用此结构,仍然是一个挑战。,这就是我们可以根据需要包装 fetch 来处理事情的地方:,然后我们可以按如下方式使用它:,在我们的最后一个例子中,最好确保我们有一个统一的方式来处理错误。 这可能包括给用户的警报、日志记录等。,探索很有趣,但重要的是要记住,您不必总是为事物创建自己的包装器。 以下是一些流行且可能值得使用的现有选项,包括一些小于 1kb 的选项:,axios 是一个非常流行的 JS 取数据选项,它自动为我们处理了上面的几个场景。,我对 Axios 的唯一批评是它对于一个简单的数据获取包装器来说大得惊人。 因此,如果 大小是您的首要任务(我认为这通常应该是为了保持您的性能一流),您可能需要查看以下两个选项之一:,如果你喜欢 Axios,但不喜欢它会给你的包增加 11kb大小,Redaxios 是一个很好的选择,它使用与 Axios 相同的 API,但不到 1kb。,一个较新的选项是 Wretch,它是 Fetch 的一个非常薄的包装器,就像 Redaxios 一样。 Wretch 的独特之处在于它在很大程度上仍然感觉像fetch,但为您提供了处理常见状态的有用方法,这些状态可以很好地链接在一起:,最后但同样重要的是,我们不要忘记直接使用 fetch 在通过 POST、PUT 或 PATCH 发送数据时可能会遇到常见的陷阱,你能发现这段代码中的错误吗?,至少有一个,但可能是两个。,首先,如果我们发送 JSON,body 属性必须是一个 JSON 序列化的字符串:,这很容易忘记,但如果我们使用 TypeScript,这至少可以自动为我们提示。,TypeScript 不会为我们捕获的另一个错误是我们没有在此处指定 Content-Type 标头。 许多后端要求您指定它,否则它们将无法正确处理正文。,现在,我们有了一个相对健壮和安全的解决方案。,我们也可以决定在包装器中为这些常见情况添加一些安全措施。 例如使用以下代码:,现在我们可以像这样使用我们的包装器:,简单安全。 我喜欢。,虽然定义我们自己的抽象既有趣又有趣,但让我们可以指出几个流行的开源项目如何自动为我们处理这些情况:,对于 Axios 和 Redaxios,类似于我们带有原始提取的原始“有缺陷”代码的代码实际上按预期工作:,同样,对于 Wretch,最基本的示例也可以按预期工作:,最后但同样重要的是,如果你想围绕 fetch 实现自己的包装器,如果你正在使用它,我们至少要确保它是类型安全的 TypeScript。,这是我们的最终代码,包括类型定义:,当使用我们新型类型安全提取包装器时,您将遇到最后一个问题。 在typescript的 catch 块中,默认错误是任何类型(any),你可以说,哦! 我只输入错误:,呃,没错,我们不能在 TypeScript 中输入错误。 那是因为从技术上讲,你可以在任何地方将任何东西放入 TypeScript。 以下是所有有效的 JavaScript/TypeScript,理论上可以存在于任何 try 块中,更不用说 fetch 本身可能会抛出它自己的错误,这不是 ResponseError,例如网络错误,例如没有可用的连接。,我们也可能不小心在我们的 fetch 包装器中有一个合法的错误,它会抛出其他错误,比如 TypeError,因此,此包装器的最终、干净且类型安全的用法类似于:,在这里,我们可以使用 instanceof 检查 err 是否是 ResponseError 实例,并在错误响应的条件块中获得完整的类型安全。,然后,如果发生任何意外错误,我们也可以重新抛出错误,并使用 JavaScript 中新的 cause 属性转发原始错误详细信息,以便更好地调试。,最后,最好不要总是为每个 HTTP 调用的每个可能的错误状态都定制一个switch。,将我们的错误处理封装到一个可重用的函数中会更好,我们可以在处理任何我们知道需要特殊逻辑的一次性情况后将其用作回退,因为该调用是该调用所独有的。,例如,我们可能有一种常用的方式,希望用“哎呀,对不起,请联系技术支持”消息提醒用户出现500问题,或者对于401问题,如果没有更具体的方式来处理这个特定请求的状态,就会使用“请再次登录”消息。,在实践中,它可以是这样的:,我们可以这样实现:,这是我认为Wretch的亮点之一,因为上面的代码可能类似于:,使用Axios或Redaxios,看起来与我们最初的示例类似,这样就完成了!,如果不清楚,我个人建议使用现成的包装器来实现fetch,因为它们可能非常小(1-2kb),通常有更多的文档、测试和社区,而且已经被其他人证明和验证了是一个有效的解决方案。,但这一切都说了,无论你是选择手动使用fetch,编写自己的包装器,还是使用开源包装器——为了你的用户和你的团队,请确保正确地获取你的数据。

文章版权声明

 1 原创文章作者:cmcc,如若转载,请注明出处: https://www.52hwl.com/18725.html

 2 温馨提示:软件侵权请联系469472785#qq.com(三天内删除相关链接)资源失效请留言反馈

 3 下载提示:如遇蓝奏云无法访问,请修改lanzous(把s修改成x)

 免责声明:本站为个人博客,所有软件信息均来自网络 修改版软件,加群广告提示为修改者自留,非本站信息,注意鉴别

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023年3月5日 上午12:00
下一篇 2023年3月7日 下午10:34