接口如何优雅的串行

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

一、回调

promise还未出世以前,回调是最多见的串行方案,可是若是回调嵌套过多会致使代码的可读性很是差,不便于维护。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>
  )
}

请求回调async

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

二、promise

promise的出现就是为了解决上面嵌套回调,采用更加优雅的方式(链式调用)书写回调函数

使用promise实现上面回调fetch

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对象this

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中的thenspa

三、async/await

promise链式回调的方式也会出现很长的状况,其实对于开发人员最直观的方法就是执行完一个再执行下一个的这种同步式写法。而async/await就是在这种设想下出现的。code

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 '';
  }

四、一些使用常见错误

假设表格接口须要单号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 '';
  }`
相关文章
相关标签/搜索