问题背景
现在看一道题目。是某厂的一个晋升题。异步传染性就是 当某一个函数节点是异步的时候 那他接下来的所有函数的调用都必须是异步

现在需要有什么办法可以消除函数中的副作用,使其变成同步的函数式编程。有人会讲,把async await 去掉不就好了吗,当然不可以因为 请求数据本身的操作是异步的
去掉 就返回了Promise 而不是我们想要的结果。返回的就会是一个Promise 我们希望能正常的接收结果

解决思路
函数开始=====>Fetch =====> 引发错误 =====> 函数结束 ======>缓存=====>函数继续

1. 首先必须在请求第一个函数做处理,首先请求是多次的 所以我们必须用数组来接受请求获得的参数,在他有缓存的时候 停止循环三次循环 直接返回缓存中的数据
JavaScript
function getList() {
// 此处发送一个异步请求
return fetch('/list.json')
}
function task1() {
return getList()
}
function task2() {
return task1()
}
function task3() {
return task2()
}
/* 我们先写一个main函数 */
function main() {
const task3Run = task3()
console.log(task3Run)
}
function run(fn) {
/* 判断是否为promise函数 */
const cache = []
let i = 0
const _originalFetch = window.fetch
window.fetch = (...args) => {
/* 发送请求,且报错 */
/* 判断缓存如果存在,则交付缓存 */
if (cache[i]) {
if (cache[i].status == 'fulfillled') {
return cache[i].data
} else if (cache[i].status == 'rejected') {
throw cache[i].err
}
}
const result = {
status: 'pending',
data: null,
err: null
}
cache[i++] = result
const prom = _originalFetch(...args)
.then(res => res.json())
.then((resolve)=> {
result.status = 'fulfillled'
result.data = resolve
}, (inject) => {
result.status = 'rejected'
result.err = inject
})
// 报错
throw prom
}
try {
fn()
} catch (err) {
if (err instanceof Promise) {
const reRun = () => {
i = 0;
fn()
}
err.then(reRun, reRun)
}
}
}
run(main)
当手动定义了缓存的格式,那就可以自己判定缓存的类型 来决定报错 还是正常返回数据
- 当成功的时候 返回正常的data
- 当失败的时候 抛出错误 注意 不是retun 否则后续的try catch接收不到
接下来就是手动报错 让函数停止 并且使用try catch捕获错误 来进行第二次返回缓存的函数请求
- 手动报错可以把请求的promise 抛出
- 在error中判定是否属于promise 而进行重复第二次请求
判断error是否是promise 而进行第二次请求 同时将下标清0

实际用到的地方
JSX
const useResource = getUserResource()
function profilePage(){
return <Suspense fallback={<div>Loading...</div>} >
<ProfileDetails />
<ProfilePosts />
</Suspense>
}
function ProfileDetails(){
const user = useResource(userId)
return <h1>{user.name}</h1>
}
function ProfilePosts(){
const posts = useResource(userId, 'posts')
return <ul>{posts.map(post => (
<li key={post.id}>{post.text}</li>
))}</ul>
}
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(<ProfilePage />)
vue 一般会要求中间组件返回promise
但在react中suspance组件是将中间组件是同步的
他会等到中间组件抛出异常再次执行中间的函数。类似于前面实现的效果
发表回复