在平时开发中,虽然我们都会尽可能的去避免接口串行调用,但是在某种特定场景下无法避免要这样做。下面将介绍一些常见的方法以及存在的问题

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直接返回得到一个含有userIdpromise对象

fecthUserInfo = async () => {
    try {
      const { code, data } = await fecthUserInfo();
      if (code === 200 && !!data) {
        return data.userId;
      }
    } catch (error) {
      console.log(error);
    }
    return '';
  }

image.png
对于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 '';
  }

上面会在将不能获取到idfecthUserInfo方法中不会等到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 '';
  }`

记得要微笑
1.9k 声望4.5k 粉丝

知不足而奋进,望远山而前行,卯足劲,不减热爱。


引用和评论

0 条评论