跳到主要内容

异步传染性

2023年12月29日
柏拉文
越努力,越幸运

一、认识


function request() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('done');
}, 1000);
});
}

async function foo1(){
let result = await request();
return result;
}

async function foo2(){
let result = await foo1();
return result;
}

async function run(){
let result = await foo2();
return result;
}

如上所示, request 是异步的, 导致了 foo1foo2run 变成了 async function。类似这样的现象叫做异步传染性

二、消除


什么是消除异步传染性呢? 就是希望 foo1foo2run 不要加入 async/await, 变成纯函数调用, 实现如下:

function request(url, ...args) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('url', url);
resolve('done');
}, 1000);
});
}

function foo1() {
let result = request('http://www.baidu.com', 1, 2, 3);
return result;
}

function foo2() {
let result = foo1();
return result;
}

function main() {
let result = foo2();
console.log(result);
}

function runMain(main) {
const promiseMap = new Map();
const originRequest = request;

request = function (url, ...args) {
const mapKey = url + JSON.stringify(args);
if (promiseMap.has(mapKey)) {
const promise = promiseMap.get(mapKey);
if (promise.state === 'fulfilled') {
return promise.result;
} else if (promise.state === 'rejected') {
throw promise.error;
}
} else {
let curr = originRequest(url, ...args)
.then(res => {
promiseMap.set(mapKey, {
state: 'fulfilled',
result: res
});
})
.catch(error => {
promiseMap.set(mapKey, {
state: 'rejected',
error: error
});
});
throw curr;
}
};

try {
main();
} catch (error) {
if (error instanceof Promise) {
error.then(main, main).finally(() => (request = originRequest));
}
}
}

runMain(main);