我们js是单线程,如果想要获取异步代码并且执行顺序还得是同步的话,我们可以用async 和await实现,这个应该都不陌生对吧
但是像例如下面这种例子,我main函数里返回一个promise,可以实现获取异步信息,所以后面函数要想调用必须得加上async awiat去等待数据获取再返回,这样如果是函数式编程的话就会形成大问题,只要有一个函数返回的是promise,后面函数如果想要返回正确的数据就得增加async和await去实现,无形中增加了代码量和维护
function main(){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('收到数据并返回信息')
},1000)
})
}
async function f1(){
return await main()
}
async function f2(){
let info = await f1()
console.log(info);
}
f2() // 过一秒后打印 ‘收到数据并返回信息’
所以有没有什么方法可以消除异步函数的传染性呢?😱其实是可以的,这是我再一些大牛那看到类似下面这段代码就能实现
// 定义一个执行函数
function eliminateAsync(func){
let i = 0
let cache = [] // 用于缓存数据
let _originMain = main // 把异步函数赋值到一个变量供后面执行
window.main = (...arg)=>{ // 重新定义异步函数
// 判断缓存中有没有数据,第一次肯定没有
if(cache[i]){
// 如果有缓存数据
// 如果状态是fulfilled的,就返回缓存数据
if(cache[i].status === 'fulfilled'){
return cache[i].data
}else{
// 如果异步函数执行错误了就返回错误信息
throw cache[i].error
}
}
let result = {
status: 'pending',
data: null,
error: null
}
// 保存缓存信息,第一次缓存数据是假缓存
cache[i++] = result
// 执行一函数,第一次不等待函数执行完,执行下面的抛出错误 throw pro
let pro = _originMain(...arg).then(
(resp)=> {
// 把数据缓存起来
result.status = 'fulfilled'
result.data = resp
},
(err)=> {
// 把错误数据缓存起来
result.status ='rejected'
result.error = err
}
)
throw pro
}
try{
func()
}catch(err){
if(err instanceof Promise){
const reRun = ()=>{
i = 0
func()
}
// 接收到抛出的错误后,再等待异步函数执行完成后重新运行传进来的函数,下次运行
// 就能拿到缓存的数据了,因为异步函数已经执行完毕,缓存已经保存了
err.then(reRun,reRun)
}
}
}
function main(){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('收到反馈和案说法')
},1000)
})
}
function f1(){
return main()
}
function f2(){
// 这里就不需要增加async和await了
console.log(11) // 其实你会发现这个打印执行了2次,明白其中道理就会知道为什么会打印2次
let user = f1()
console.log(user);
}
eliminateAsync(f2) // 一秒过后打印 ‘收到数据并返回信息’
这里面的逻辑呢其实就是在运行异步函数时,不等待它返回,而是直接执行后面代码,等异步函数执行完后再把数据缓存起来,再一次调用传进去的函数获取到缓存信息并返回
我第一次看也是一脸懵,可以反复多看几次就能明白