在平时开发中,虽然我们都会尽可能的去避免接口串行调用,但是在某种特定场景下无法避免要这样做。下面将介绍一些常见的方法以及存在的问题
1、回调
在promise
还未出世之前,回调是最常见的串行方案,但是如果回调嵌套过多会导致代码的可读性非常差,不便于维护。
假设现在存在一种场景,需要渲染一个表格,但是表格数据接口(/tableList
)需要一个userId
作为入参,userId
只能通过用户数据接口(/user
)获取
const Main = (props: IProps) => {
const { mainStore } = props;
const { fecthUserInfo, fetchTableList } = mainStore as MainStore;
useEffect(() => {
// 将获取表格数据的方法作为回调
fecthUserInfo(fetchTableList)
})
return (
<div>
<TableList></TableList>
</div>
)
}
请求回调
fecthUserInfo = async (cb: (userId: string) => void) => {
try {
const { code, data } = await fecthUserInfo();
if (code === 200 && !!data) {
cb(data.userId)
}
} catch (error) {
console.log(error);
}
}
2、promise
promise
的出现就是为了解决上面嵌套回调,采用更加优雅的方式(链式调用)书写回调
使用promise
实现上面回调
const Main = (props: IProps) => {
const { mainStore } = props;
const { fecthUserInfo, fetchTableList } = mainStore as MainStore;
useEffect(() => {
fecthUserInfo().then((userId) => {
if (userId) {
fetchTableList(userId)
}
})
})
return (
<div>
<TableList></TableList>
</div>
)
}
因为async
函数返回的是一个promise
对象,因此可以将获取到的userId
直接返回得到一个含有userId
的promise
对象
fecthUserInfo = async () => {
try {
const { code, data } = await fecthUserInfo();
if (code === 200 && !!data) {
return data.userId;
}
} catch (error) {
console.log(error);
}
return '';
}
对于promise不熟悉的同学可以参考通俗浅显的理解Promise中的then
3、async/await
promise
链式回调的方式也会出现很长的情况,其实对于开发人员最直观的方法就是执行完一个再执行下一个的这种同步式写法。而async/await
就是在这种设想下出现的。
const Main = (props: IProps) => {
const { mainStore } = props;
const { fecthUserInfo, fetchTableList } = mainStore as MainStore;
const init = async () => {
const userId = await fecthUserInfo();
if (userId) {
fetchTableList(userId);
}
}
useEffect(() => {
init();
})
return (
<div>
<TableList></TableList>
</div>
)
}
fecthUserInfo = async () => {
try {
const { code, data } = await fecthUserInfo();
if (code === 200 && !!data) {
return data.userId;
}
} catch (error) {
console.log(error);
}
return '';
}
4、一些使用常见错误
假设表格接口需要单号id来获取,id又需要获取单号接口根据userId来获取,而userId是通过用户接口获取的。先看一种错误的写法:
const Main = (props: IProps) => {
const { mainStore } = props;
const { fecthUserInfo, fetchTableList } = mainStore as MainStore;
const init = async () => {
const id = await fecthUserInfo();
if (id) {
fetchTableList(id);
}
}
useEffect(() => {
init();
})
return (
<div>
<TableList></TableList>
</div>
)
}
@action
fetchTableList = async (userId: string) => {
try {
const { code, data } = await fetchTableData(userId);
if (code === 200 && !!data) {
runInAction(() => {
this.list = data;
})
}
} catch (error) {
console.log(error);
}
}
@action
fetchOrder = async (userId: string) => {
try {
const { code, data } = await fetchOrder(userId);
console.log(11111111)
if (code === 200 && !!data) {
return data.id;
}
} catch (error) {
console.log(error);
}
return '';
}
@action
fecthUserInfo = async () => {
try {
const { code, data } = await fecthUserInfo();
if (code === 200 && !!data) {
this.fetchOrder(data.userId)
}
} catch (error) {
console.log(error);
}
return '';
}
上面会在将不能获取到id
,fecthUserInfo
方法中不会等到this.fetchOrder(data.userId)
请求完在返回,因为this.fetchOrder
是一个异步函数,会先执行后面的return ''
,因此得到的id
是空的。
只需要将fecthUserInfo
稍作修改就可正确获取
@action
fecthUserInfo = async () => {
try {
const { code, data } = await fecthUserInfo();
if (code === 200 && !!data) {
return await this.fetchOrder(data.userId)
}
} catch (error) {
console.log(error);
}
return '';
}`
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。