返回顶部
首页 > 资讯 > 精选 >useEffect中不能使用async的原理是什么
  • 428
分享到

useEffect中不能使用async的原理是什么

2023-07-02 16:07:10 428人浏览 安东尼
摘要

本篇内容介绍了“useEffect中不能使用async的原理是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!当页面中使用 useEffe

本篇内容介绍了“useEffect中不能使用async的原理是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

当页面中使用 useEffect 的时候,会在初始化的时候执行 mountEffect 如下:

useEffect: function(create, deps) {  currentHookNameInDev = "useEffect";  mountHookTypesDev();  checkDepsAreArrayDev(deps);  return mountEffect(create, deps);},

执行 mountEffect 的时候执行 mountEffectImpl 如下:

function mountEffectImpl(fiberFlags, hookFlags, create, deps) {  var hook = mountWorkInProgresshook();  var nextDeps = deps === void 0 ? null : deps;  currentlyRenderingFiber$1.flags |= fiberFlags;  hook.memoizedState = pushEffect(HasEffect | hookFlags, create, void 0, nextDeps);}

之后执行 pushEffect,在 pushEffect 中会创建一个 effect 节点,然后添加到当前函数对应 fiber 的 updateQueue 上面,数据结构是一个环链。

function pushEffect(tag, create, destroy, deps) {  var effect = {    tag,    create,    destroy,    deps,    next: null  };  var componentUpdateQueue = currentlyRenderingFiber$1.updateQueue;  if (componentUpdateQueue === null) {    componentUpdateQueue = createFunctionComponentUpdateQueue();    currentlyRenderingFiber$1.updateQueue = componentUpdateQueue;    componentUpdateQueue.lastEffect = effect.next = effect;  } else {    var lastEffect = componentUpdateQueue.lastEffect;    if (lastEffect === null) {      componentUpdateQueue.lastEffect = effect.next = effect;    } else {      var firstEffect = lastEffect.next;      lastEffect.next = effect;      effect.next = firstEffect;      componentUpdateQueue.lastEffect = effect;    }  }  return effect;}

中间又是一大堆调度,协调的逻辑,不是我们关注的重点,这里省略掉直接进入到 schedulePassiveEffects,这个函数作用是从函数组件对应的 fiber 上获取上面挂载的 effect,然后将 effect 和 fiber 堆到 pendingPassiveHookEffectsUnmount 和 pendingPassiveHookEffectsMount 这个两个队列中

function schedulePassiveEffects(finishedWork) {  var updateQueue = finishedWork.updateQueue;  var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;  if (lastEffect !== null) {    var firstEffect = lastEffect.next;    var effect = firstEffect;    do {      var _effect = effect      , next = _effect.next      , tag = _effect.tag;      if ((tag & Passive$1) !== NoFlags$1 && (tag & HasEffect) !== NoFlags$1) {        //         enqueuePendingPassiveHookEffectUnmount(finishedWork, effect);        enqueuePendingPassiveHookEffectMount(finishedWork, effect);      }      effect = next;    } while (effect !== firstEffect);  }}

这里是推入的逻辑,只展示推入挂载队列的方法,推入卸载队列是一样的

function enqueuePendingPassiveHookEffectMount(fiber, effect) {  pendingPassiveHookEffectsMount.push(effect, fiber);  if (!rootDoesHavePassiveEffects) {    rootDoesHavePassiveEffects = true;    scheduleCallback(NORMalPriority$1, function() {      flushPassiveEffects();      return null;    });  }}

之后又是一大推调度,协调的逻辑,等待协调执行完毕后,之后会进入 flushPassiveEffectsImpl ,函数太长了,只贴出相关的部分,逻辑是循环挂载 effect 队列中的每一个 effect 传入到 invokePassiveEffectCreate 执行

// ...var mountEffects = pendingPassiveHookEffectsMount;pendingPassiveHookEffectsMount = [];for (var _i = 0; _i < mountEffects.length; _i += 2) {  var _effect2 = mountEffects[_i];  var _fiber = mountEffects[_i + 1];  {    setCurrentFiber(_fiber);    {      invokeGuardedCallback(null, invokePassiveEffectCreate, null, _effect2);    }    if (hasCaughtError()) {      if (!(_fiber !== null)) {        {          throw Error("Should be working on an effect.");        }      }      var _error4 = clearCaughtError();      captureCommitPhaseError(_fiber, _error4);    }    resetCurrentFiber();  }}// ...

这个函数会获取 create 并执行,然后将执行结果挂载到 destroy 上,这里的 create 就是 useEffect 中的第一个参数,从这里可以看出,如果有返回值,那么 destroy 就是第一个函数的返回值,没有就是 undefined

function invokePassiveEffectCreate(effect) {  var create = effect.create;  effect.destroy = create();}

卸载的时候会通过函数组件对应的 fiber 获取 effect 链表,然后遍历链表,获取环链上的每一个节点,如果 destroy 不是 undefined 就执行,所以如果 useEffect 第一个参数传入 async, 那么这里的 destroy 就是一个 promise 对象,对象是不能执行的,所以报错。

function commitHookEffectListUnmount(tag, finishedWork) {  var updateQueue = finishedWork.updateQueue;  var lastEffect = updateQueue !== null ? updateQueue.lastEffect : null;  if (lastEffect !== null) {    var firstEffect = lastEffect.next;    var effect = firstEffect;    do {      if ((effect.tag & tag) === tag) {        // Unmount        var destroy = effect.destroy;        effect.destroy = undefined;        if (destroy !== undefined) {          destroy();        }      }      effect = effect.next;    } while (effect !== firstEffect);  }}

既然知道了原因那么,解决方案就非常简单,直接手写一个自定义 hook,包裹一下就可以处理这个问题了,hook 实现如下。

import { useEffect } from 'React'export default function useAsyncEffect<T, U extends any[]>(  method: () => Promise<T>,  deps: U) {  useEffect(() => {    (async () => {      await method()    })()  }, deps)}

使用:

import React, { useState } from 'react'import { useAsyncEffect } from './useAsyncEffect'export default function Demo() {  const [count, setCount] = useState(0)  function fetchData(): Promise<number> {    return new Promise((resolve) => {      setTimeout(() => {        resolve(count + 1)      }, 2000)    })  }  useAsyncEffect(async () => {    const count = await fetchData()    setCount(count)  }, [fetchData])  return (    <div>{count}</div>  )}

这里其实有问题,因为返回值永远是undefined,你可以开动脑筋尝试修复一下。

“useEffect中不能使用async的原理是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: useEffect中不能使用async的原理是什么

本文链接: https://lsjlt.com/news/343179.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • useEffect中不能使用async的原理是什么
    本篇内容介绍了“useEffect中不能使用async的原理是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!当页面中使用 useEffe...
    99+
    2023-07-02
  • useEffect中不能使用async原理详解
    目录引言具体代码分析执行 mountEffect执行 mountEffectImpl执行 pushEffect进入到 schedulePassiveEffects推入卸载队列invo...
    99+
    2024-04-02
  • 避免async await的使用及原理是什么
    这篇文章主要讲解了“避免async await的使用及原理是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“避免async await的使用及原理是什么”吧!谎言和as...
    99+
    2023-07-02
  • 使用代理IP不能上网的原因是什么
    这篇文章主要讲解了“使用代理IP不能上网的原因是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“使用代理IP不能上网的原因是什么”吧!大概大家对代理IP并不陌生,特别是因特网工作者,经常需...
    99+
    2023-06-20
  • 不能在PHP中使用泛型的原因是什么
    小编给大家分享一下不能在PHP中使用泛型的原因是什么,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!为什么我们不能在 PHP 中使用泛型我们将深入探讨泛型和 PHP...
    99+
    2023-06-29
  • c++中async的作用是什么
    在C++中,async是一个用来创建异步任务的函数模板。它的作用是创建一个异步任务,并返回一个std::future对象,用来获取异...
    99+
    2024-03-06
    c++
  • c++中async的用法是什么
    在C++中,std::async函数用于创建一个异步任务,并返回一个std::future对象,该对象可以用于获取异步任务的结果。 ...
    99+
    2024-03-06
    c++
  • swoole不能用sleep的原因是什么
    这篇文章主要介绍“swoole不能用sleep的原因是什么”,在日常操作中,相信很多人在swoole不能用sleep的原因是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”swoole不能用sleep的原因...
    99+
    2023-06-30
  • 代理ip不能上网的原因是什么
    这篇文章主要介绍了代理ip不能上网的原因是什么,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。许多网络工作者需要使用代理IP。一些人会发现ip不能在使用代理IP的过程中使用。原...
    99+
    2023-06-20
  • 免费IP不能用的原因是什么
    这篇文章主要讲解了“免费IP不能用的原因是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“免费IP不能用的原因是什么”吧!1、免费代理IP可用性低。2、免费的代理IP,使用起来比较麻烦。选...
    99+
    2023-06-20
  • async await的用法是什么
    async/await 是 JavaScript 中用于处理异步操作的关键字组合。async 关键字用于声明一个函数是异步函数,该函...
    99+
    2023-10-07
    async
  • mongodb使用原理是什么
    MongoDB使用原理是基于文档的NoSQL数据库系统。其核心原理包括以下几个方面:1. 文档存储:MongoDB存储的基本单位是文...
    99+
    2023-09-11
    mongodb
  • Array.reduce使用原理是什么
    这篇文章主要介绍“Array.reduce使用原理是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Array.reduce使用原理是什么”文章能帮助大家解决问题。重新了解 Array.reduc...
    99+
    2023-07-05
  • MySQL中不使用Text类型的原因是什么
    MySQL中不使用Text类型的原因是什么,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。众所周知,MySQL广泛应用于互联网的OLTP(联机事...
    99+
    2024-04-02
  • MySQL中不建议使用SELECT *的原因是什么
    本篇内容介绍了“MySQL中不建议使用SELECT *的原因是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!“不要使用...
    99+
    2023-06-29
  • Java中ThreadLocal的原理是什么及怎么使用
    这篇文章主要介绍“Java中ThreadLocal的原理是什么及怎么使用”,在日常操作中,相信很多人在Java中ThreadLocal的原理是什么及怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Jav...
    99+
    2023-07-06
  • cpu使用不高但是物理内存高的原因是什么
    小编给大家分享一下cpu使用不高但是物理内存高的原因是什么,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!所有的程序运行都在使用内存,特别是杀毒软件或者开机启动项,...
    99+
    2023-06-20
  • JS循环中正确使用async、await的方法是什么
    JS循环中正确使用async、await的方法是什么,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。概览(循环方式 - 常用)formapforEachfilter声明遍历的...
    99+
    2023-06-22
  • haproxy实现功能以及keepalived的使用原理是什么
    这篇文章将为大家详细讲解有关haproxy实现功能以及keepalived的使用原理是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。haproxy能够实现的功能4层负载均衡,透明代理,7...
    99+
    2023-06-05
  • ADO.NET性能原理是什么
    本篇内容介绍了“ADO.NET性能原理是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1.ADO.NET性能装载XML数据在 ADO.N...
    99+
    2023-06-17
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作