我发现自己不断为异步调用编写相同形状的代码,因此我尝试将其包装成抽象一些细节的东西。我希望在onError回调中可以传递正在执行的异步函数的引用,以便某些中间件在必要时可以实现重试逻辑。也许这是一种代码气味,我以错误的方式解决了这个问题,但我很好奇是否有可能或是否有其他建议可以解决此问题。
const runAsync = (asyncFunc) => {
let _onBegin = null;
let _onCompleted = null;
let _onError = null;
let self = this;
return {
onBegin(f) {
_onBegin = f;
return this;
},
onCompleted(f) {
_onCompleted = f;
return this;
},
onError(f) {
_onError = f;
return this;
},
async execute() {
if (_onBegin) {
_onBegin();
}
try {
let data = await asyncFunc();
if (_onCompleted) {
_onCompleted(data);
}
} catch (e) {
if (_onError) {
_onError(e ** /*i'd like to pass a function reference here as well*/ ** );
}
return Promise.resolve();
}
},
};
};
await runAsync(someAsyncCall())
.onBegin((d) => dispatch(something(d)))
.onCompleted((d) => dispatch(something(d)))
.onError((d, func) => dispatch(something(d, func)))
.execute()
我想您可以使用custom hook。像-
import { useState, useEffect } from 'react';
const useAsync = (f) => {
const [state, setState] =
useState({ loading: true, result: null, error: null });
const runAsync = async () => {
try {
setState({ ...state, loading: false, result: await f() })
}
catch (err) {
setState({ ...state, loading: false, error: err })
}
}
useEffect(runAsync, []);
return state;
}
现在我们可以在组件中使用它-
const FriendList = ({ userId }) => {
const response =
useAsync(somePromiseReturningCall())
if (response.error)
return <Error text="response.error.message" />
else if (response.loading)
return <Loading />
else
return <ul>{response.result.map(Friend)}</ul>
}