【React】将 useReducer 应用于 Web Worker,擦出奇妙的火花

简介: 有这么一个场景,当加载一个网页时,它突然变得无响应,直到所有的资源完全加载完毕才响应。但是,当资源加载时,用户可能无法执行页面上的某些功能,比如单击、选择或拖动元素。这个时候你可能会想到使用 Web workers帮助我们解决这个问题。

有这么一个场景,当加载一个网页时,它突然变得无响应,直到所有的资源完全加载完毕才响应。但是,当资源加载时,用户可能无法执行页面上的某些功能,比如单击、选择或拖动元素。这个时候你可能会想到使用 Web workers帮助我们解决这个问题。
在本文中,我们将学习如何在 React 应用程序中使用web workers。我们还将学习通过 useWorkerizedReducer 在web worker 中使用 useReducer Hook。

web worker

web worker 是一个JavaScript脚本,它在后台运行,不会干扰其他脚本的执行。

因为JavaScript是单线程语言,它不能同时运行多个脚本,这对于运行大型计算脚本来说是一个问题。Web worker帮助在后台加载繁重的计算脚本,而不会影响页面的性能。

语法

const worker = new Worker(new URL("./worker.js", import.meta.url), {
 type: "module",
});

Worker 构造函数接受两个参数;第一个是 worker 文件名,第二个是worker 的类型。类型可以是 classic,或者是 module。如果未指定类型,则默认类型为 classic

在本文中,我们将使用module类型,因为 reducer 只能在组件中使用。要在 web worker 组件中使用 import 函数,我们必须将import.meta. URL 添加到 URL 构造函数中。

useReducer

useReducer是一个React Hook,用于存储和更新状态。它接受三个参数:reducer, initial state,作为最后一个参数,initial function,它是可选的:

const [state, dispatch] = useReducer(reducer, initialArg, init);

useReducer 返回一个包含当前 state 值的数组,以及一个 dispatch 函数,你可以向该 dispatch 函数提供要执行的操作。

dispatch 函数接受指定要执行的操作类型的对象。它本质上是将 action 的类型传递给 reducer 函数,而 reducer 函数用于更新 state

reducer 函数

reducer 是一个接受两个参数的函数,当前 stateaction 对象。它使用接收到的 action 来确定 state 的更改并返回新 state

下面的代码演示了如何使用 reducer 函数来改变 state:

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};

   default:
      throw new Error();
  }
}

每当 reducer 函数被 action.type 触发时,它就会将新的 state 作为 reducer 函数内部的更改返回。

action 是一种对象类型,它指示 reducer 如何更改 state。它必须具有 type 属性。可以在条件语句中使用 action.type 来决定 state 如何更改。

为了让 reducer 函数在 web worker 中运行,我们必须使用useWorkerizedReducer

useWorkerizedReducer

useWorkerizedReducer 类似于 useReducer,除了它允许 reducer 在 worker 中执行,还允许我们创建一个动态的 React 应用。

useWorkerizedReducer 允许在不影响应用程序响应的情况下将长时间运行的计算放置在 reducer 中。useWorkerizedReducer 负责向 worker 提供 useReducer 的功能。

通过将 reducerstate 复制到主线程,useWorkerizedReducer 在工作线程和主线程之间架起了桥梁。reducer 操作 worker 的 state 对象,使用 postMessage() 来保持复制主线程的当前状态。

实战:构建一个简单的计数器应用程序

为了学习如何在web worker中放置 Reducer,让我们创建一个简单的计数器程序,它将在当前 state 发生改变时返回。

首先,打开命令行,输入以下命令:

npx create-react-app my-app
cd my-app
npm start

在成功安装应用程序之后,我们需要将 useWorkerizedReducer 作为程序的依赖项来使用它。安装 “useWorkerizedReducer”,在终端中执行如下命令:

npm i use-workerized-reducer

现在我们已经成功安装了useWorkerizedReducer,让我们接着创建一个worker.js 文件。

创建 worker.js

因为我们在 worker.js 文件中使用了 reducer,所以我们将在 src 文件夹中创建 worker.js 文件: 单击“创建新文件”,将其命名为 worker.js,然后将其保存到 src 文件夹中,如下所示:

img

现在我们已经创建了 worker.js 文件,让我们在其中添加下面的 reducer 代码:

// worker.js
import { initWorkerizedReducer } from "use-workerized-reducer";

initWorkerizedReducer(
 "counter", //  reducer's name
 async (state, action) => {
   switch (action.type) {
     case "increment":
       state.counter += 1;
       break;
     case "decrement":
       state.counter -= 1;
       break;
     default:
       throw new Error();
   }
 }
);

在上面的代码中,我们从 use-workerizedreducer 中导入了initWorkerizedReducer

initWorkerizedReducer() 接受两个参数:

  • 第一个是 reducer 的名称:counter。
  • 第二个是一个异步函数。

现在我们已经准备好了 worker.js 文件,我们需要从 use- workerizedreducer /react 中导入 useWorkerizedReducer ,这让我们可以从 worker 文件中调用 reducer 函数:

// main.js
import { render, h, Fragment } from "react";
import { useWorkerizedReducer } from "use-workerized-reducer/react";

const worker = new Worker(new URL("./worker.js", import.meta.url), {
 type: "module",
});

function App() {
 // 一个 worker 可以包含多个不同名的 reducer

 const [state, dispatch, busy] = useWorkerizedReducer(
   worker,
   "counter", // Reducer name
   { counter: 0 } // Initial state
 );

 return (
   <>
     Count: {state.counter}
     <button disabled={busy} onClick={() => dispatch({ type: "decrement" })}>
       -
     </button>
     <button disabled={busy} onClick={() => dispatch({ type: "increment" })}>
       +
     </button>
   </>
 );
}

export default App;

useWorkerizedReducer 函数接受三个参数并返回单个值:

  • 当前state是第一个参数;
  • action 是第二个参数;
  • 初始状态是第三个参数。

处理的数据是 statedispatch 函数执行传递给 reducer 函数的action

Busy将一直为 true,直到 worker 的初始状态 counter 成功复制到 worker。在此之后,如果 actions 仍在处理中,则 Busy 返回 true,否则返回 false。

reducer 根据 action 类型改变状态。action 类型 increment, decrement和reset都是在 dispatch 时更新 state 的 action 类型。

初始状态为{counter: 0}。当递增操作类型被 dispatch 时,我们简单地设置 count {state.Count + 1}

结尾

在这篇文章中,我们简要介绍了 web worker 和 useReducer,以及如何构造和添加 web worker 文件到 React 应用程序中。

我们还讨论了useWorkerizedReducer,它为 web worker 带来了useReducer 的功能。最后,我们介绍了在useWorkerizedReducer的帮助下在 web worker中使用 reducer。

相关文章
|
2月前
|
存储 监控 安全
如何在Python Web开发中确保应用的安全性?
如何在Python Web开发中确保应用的安全性?
|
2月前
|
前端开发 JavaScript
探索现代Web应用的微前端架构
【10月更文挑战第40天】在数字时代的浪潮中,Web应用的发展日益复杂多变。微前端架构作为一种新兴的设计理念,正逐步改变着传统的单一前端开发模式。本文将深入探讨微前端的核心概念、实现原理及其在实际项目中的应用,同时通过一个简单的代码示例,揭示如何将一个庞大的前端工程拆分成小而美的模块,进而提升项目的可维护性、可扩展性和开发效率。
|
18天前
|
弹性计算 Java 关系型数据库
Web应用上云经典架构实践教学
Web应用上云经典架构实践教学
Web应用上云经典架构实践教学
|
26天前
|
Kubernetes 安全 Devops
有效抵御网络应用及API威胁,聊聊F5 BIG-IP Next Web应用防火墙
有效抵御网络应用及API威胁,聊聊F5 BIG-IP Next Web应用防火墙
59 10
有效抵御网络应用及API威胁,聊聊F5 BIG-IP Next Web应用防火墙
|
18天前
|
弹性计算 Java 数据库
Web应用上云经典架构实战
本课程详细介绍了Web应用上云的经典架构实战,涵盖前期准备、配置ALB、创建服务器组和监听、验证ECS公网能力、环境配置(JDK、Maven、Node、Git)、下载并运行若依框架、操作第二台ECS以及验证高可用性。通过具体步骤和命令,帮助学员快速掌握云上部署的全流程。
|
2月前
|
前端开发 JavaScript UED
在数字化时代,Web 应用性能优化尤为重要。本文探讨了CSS与HTML在提升Web性能中的关键作用及未来趋势
在数字化时代,Web 应用性能优化尤为重要。本文探讨了CSS与HTML在提升Web性能中的关键作用及未来趋势,包括样式表优化、DOM操作减少、图像优化等技术,并分析了电商网站的具体案例,强调了技术演进对Web性能的深远影响。
43 5
|
2月前
|
机器学习/深度学习 人工智能 JavaScript
JavaScript和TypeScript的未来发展趋势及其在Web开发中的应用前景
本文探讨了JavaScript和TypeScript的未来发展趋势及其在Web开发中的应用前景。JavaScript将注重性能优化、跨平台开发、AI融合及WebAssembly整合;TypeScript则强调与框架整合、强类型检查、前端工程化及WebAssembly的深度结合。两者结合发展,特别是在Vue 3.0中完全采用TypeScript编写,预示着未来的Web开发将更加高效、可靠。
53 4
|
18天前
|
弹性计算 负载均衡 安全
云端问道-Web应用上云经典架构方案教学
本文介绍了企业业务上云的经典架构设计,涵盖用户业务现状及挑战、阿里云业务托管架构设计、方案选型配置及业务初期低门槛使用等内容。通过详细分析现有架构的问题,提出了高可用、安全、可扩展的解决方案,并提供了按量付费的低成本选项,帮助企业在业务初期顺利上云。
|
2月前
|
监控 安全 测试技术
如何在实际项目中应用Python Web开发的安全测试知识?
如何在实际项目中应用Python Web开发的安全测试知识?
36 4
|
2月前
|
机器学习/深度学习 数据采集 Docker
Docker容器化实战:构建并部署一个简单的Web应用
Docker容器化实战:构建并部署一个简单的Web应用