侧边栏壁纸
  • 累计撰写 47 篇文章
  • 累计创建 2 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

React:Suspense的原理,消除异步的传染性

消除异步的传染性

前端开发中通常指的是通过一些技术手段,避免异步操作在整个代码库中蔓延,导致原本可以是同步的函数也必须变成异步。

原代码:

async function getUser() {
	return await fetch('./1.json)
}

async function m1() {
	return await getUser()
}

async function main() {
	const data = await m1()
}

重写 fetch:

function getUser() {
	return fetch('./1.json)
}

function m1() {
	return getUser()
}

function main() {
	const user = m1()
	console.log(user)
}

function run(func) {
	const oldFetch = window.fetch;
	const cache = {
		status: 'pending', // pending, fulfilled, rejected
		value: null
	}
	function newFetch(...args) {
		if(cache.status === 'fulfilled') {
			return cache.value;
		}
		else if (cache.status === 'rejected') {
			throw cache.value;
		}
		const p = oldFetch(...args).then(res=> res.json())
		.then(res => {
			cache.status = 'fulfilled';
			cache.value = res;
		})
		.catch(err => {
			cache.status = 'rejected';
			cache.value = err;
		})
		throw p;
	}
	window.fetch = newFetch;
	try{
		func();
	}catch(err) {
		if(err instaceof Promise) {
			err.finally(() => {
				window.fetch = newFetch;
				func()
				window.fetch = oldFetch;
			})
		}
	}
	window.fetch = oldFetch;
}
run(main)
什么是 Suspense?

Suspense 是 React 16.6+ 引入的数据获取代码分割的并发特性,用于更优雅地处理异步操作。在 React 中就是使用了这样的原理

// 使用 Suspense 进行数据获取
import { Suspense } from 'react';
import { fetchData } from './api';

// 创建一个资源
const resource = fetchData('/api/user');

function UserProfile() {
  // 读取数据(可能会挂起)
  const user = resource.read();
  return <div>{user.name}</div>;
}

function App() {
  return (
    <Suspense fallback={<div>Loading user...</div>}>
      <UserProfile />
    </Suspense>
  );
}
实现 Suspense 数据获取
// 创建资源包装器
function wrapPromise(promise) {
  let status = 'pending';
  let result;
  
  const suspender = promise.then(
    (r) => {
      status = 'success';
      result = r;
    },
    (e) => {
      status = 'error';
      result = e;
    }
  );
  
  return {
    read() {
      if (status === 'pending') {
        throw suspender; // 这会触发 Suspense
      } else if (status === 'error') {
        throw result; // 这会触发 Error Boundary
      } else if (status === 'success') {
        return result;
      }
    }
  };
}

// 使用示例
function fetchUser(id) {
  return wrapPromise(
    fetch(`/api/user/${id}`).then(res => res.json())
  );
}
0

评论区