仅供参考。
使用CPromise包,您可以取消您的Promise链,包括嵌套的链。它支持AbortController和生成器作为ECMA异步函数的替代品。目前该项目处于beta阶段。
生成器用法Live Demo:
import CPromise from "c-promise2";
const chain = CPromise.resolve()
.then(function* () {
const value1 = yield new CPromise((resolve, reject, { onCancel }) => {
const timer = setTimeout(resolve, 1000, 3);
onCancel(() => {
console.log("timer cleared");
clearTimeout(timer);
});
});
const [value2, value3] = yield [
CPromise.delay(1000, 4),
CPromise.delay(1000, 5)
];
return value1 + value2 + value3;
})
.then(
(value) => {
console.log(`Done: ${value}`);
},
(err) => {
console.log(`Failed: ${err}`);
}
);
setTimeout(() => chain.cancel(), 100);
输出:
timer cleared
Failed: CanceledError: canceled
所有阶段都可以完全取消/中止。
以下是在React中使用它的示例实时演示
export class TestComponent extends React.Component {
state = {};
async componentDidMount() {
console.log("mounted");
this.controller = new CPromise.AbortController();
try {
const json = await this.myAsyncTask(
"https://run.mocky.io/v3/7b038025-fc5f-4564-90eb-4373f0721822?mocky-delay=2s"
);
console.log("json:", json);
await this.myAsyncTaskWithDelay(1000, 123);
this.setState({ text: JSON.stringify(json) });
} catch (err) {
if (CPromise.isCanceledError(err)) {
console.log("tasks terminated");
}
}
}
myAsyncTask(url) {
return CPromise.from(function* () {
const response = yield cpFetch(url);
return yield response.json();
}).listen(this.controller.signal);
}
myAsyncTaskWithDelay(ms, value) {
return new CPromise((resolve, reject, { onCancel }) => {
const timer = setTimeout(resolve, ms, value);
onCancel(() => {
console.log("timeout cleared");
clearTimeout(timer);
});
}).listen(this.controller.signal);
}
render() {
return (
<div>
AsyncComponent: <span>{this.state.text || "fetching..."}</span>
</div>
);
}
componentWillUnmount() {
console.log("unmounted");
this.controller.abort();
}
}
使用 Hooks 和 cancel
方法
import React, { useEffect, useState } from "react";
import CPromise from "c-promise2";
import cpFetch from "cp-fetch";
export function TestComponent(props) {
const [text, setText] = useState("fetching...");
useEffect(() => {
console.log("mount");
const promise = cpFetch(props.url)
.then(function* (response) {
const json = yield response.json();
setText(`Delay for 2000ms...`);
yield CPromise.delay(2000);
setText(`Success: ${JSON.stringify(json)}`);
})
.canceled()
.catch((err) => {
setText(`Failed: ${err}`);
});
return () => {
console.log("unmount");
promise.cancel();
};
}, [props.url]);
return <p>{text}</p>;
}
useReducer
开始,以了解应用程序状态的中央存储对象的流程。还有其他关于使用useReducer
进行异步获取的问题,这也可以使您的设置更完善。 - Ross Allen