接口如何優雅的串行

在平時開發中,雖然咱們都會盡量的去避免接口串行調用,可是在某種特定場景下沒法避免要這樣作。下面將介紹一些常見的方法以及存在的問題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 '';
  }`
相關文章
相關標籤/搜索