Hi there! Just want some community feedback on my c-promise2 package that provides an extended promise class on top of the native. The library allows you to:
- cancel a promise chain (with rejection)
- use class decorators
- pause/resume your promises
- handle timeouts
- capture promise chain progress
- use internal/external AbortController for sending abort signals
- use data flow
Any thoughts, which may arise when you see a code like the following are welcome :)
It's a generic React component that uses CPromise decorators to manage the life cycle of the async code including nested JSON requests. For example, this easily lets you avoid warnings like Warning: Can’t perform a React state update on an unmounted component
when you unmount a component with running async tasks.
Demo1
import { async, listen, cancel, timeout } from "c-promise2";
import cpFetch from "cp-fetch";
export class TestComponent extends React.Component {
state = {
text: ""
};
@timeout(5000)
@listen
@async
*componentDidMount() {
console.log("mounted");
const response = yield cpFetch(this.props.url);
this.setState({ text: `json: ${yield response.text()}` });
}
render() {
return <div>{this.state.text}</div>;
}
@cancel()
componentWillUnmount() {
console.log("unmounted");
}
}
export class TestComponent extends React.Component {
state = {
text: "",
items: [],
progress: 0
};
constructor(props) {
super(props);
this.onAbortClick = this.onAbortClick.bind(this);
}
@cancel(E_REASON_CANCELED)
onAbortClick() {}
@canceled(function (err) {
console.warn(`Canceled: ${err}`);
if (err.code !== E_REASON_DISPOSED) {
this.setState({ text: err + "" });
}
})
@progress(function (progress) {
console.log(`Progress: ${progress}`);
this.setState({ progress });
})
@innerWeight(3)
@listen
@async
*componentDidMount() {
console.log("mounted");
// concurrent requests with CPromise.all:
const items = yield [
this.fetchJSON(
"https://run.mocky.io/v3/7b038025-fc5f-4564-90eb-4373f0721822?mocky-delay=2s"
),
this.fetchJSON2(
"https://run.mocky.io/v3/00758c80-8001-4bcc-bf7d-082ac3e1092b?mocky-delay=4s"
)
];
yield CPromise.delay(500); // just simulate another aync task
yield CPromise.delay(500);
yield CPromise.delay(500).weight(0);
this.setState({ text: `${items.length} requests completed`, items });
}
@timeout(15000)
@async
*fetchJSON(url) {
const response = yield cpFetch(url); // cancellable request
return yield response.json();
}
@timeout(15000)
@async
*fetchJSON2(url) {
const response = yield cpAxios(url);
return response.data;
}
render() {
return (
<div>
{this.state.text || (
<div>
<ProgressBar animated now={this.state.progress * 100 + ""} />
<button
type="button"
className="btn btn-warning"
onClick={this.onAbortClick}
>
Abort sequence
</button>
</div>
)}
<ul>
{this.state.items.map((item, i) => (
<li key={i}>{JSON.stringify(item)}</li>
))}
</ul>
</div>
);
}
@cancel(E_REASON_DISPOSED)
componentWillUnmount() {
console.log("unmounted");
}
}
Top comments (0)