动态

详情 返回 返回

跟魯迅重學 TypeScript | (五)異步處理、axios與封裝axios - 动态 详情

“不在沉默中爆發,就在沉默中滅亡”,面對日益嚴峻的國際環境,我們祖國母親沒有繼續沉默,9月25日8時44分,洲際彈道導彈精準發射。,看到這個新聞,腰也不酸了,腿也不疼了,一口上上五樓,TS 學起來更帶勁了~

異步處理

TypeScript 中,異步編程如同現代社會中的種種現象,紛繁複雜,令人眼花繚亂。而 async/await 正如那一柄利劍,能將這混沌的世界理清,使得程序員不至於深陷於回調的泥潭。

async/await 之道,表面上雖是簡化 Promise 之使用,實則背後藏着更深的精妙。它讓你在面對異步操作時,彷彿直面現實中的種種不確定性——你不能立即獲得結果,但你可以等待,甚至可以捕捉錯誤,猶如命運中的風浪,隨時可能降臨。

  • 見證 asyncawait 的簡潔力量:

    async function asyncOperation(): Promise<string> { // Promise 是內置接口
      return Promise.resolve("Hello, async world!");
    }
     
    async function run() {
      const result = await asyncOperation(); // 等待異步操作
      console.log(result);  // "Hello, async world!"
    }
     
    run();

    上述代碼中,一個異步函數 asyncOperation,明明返回的是 Promise,但在 await 的引導下,彷彿時間為你停留,結果近在咫尺。正如這世間之事,許多結果只能在漫長的等待後才能得到。通過 await,程序員不再被繁複的回調地獄所困擾,代碼流程如流水般順暢。

  • try...catch錯誤處理,正如命運中的風暴:

    // try……catch
    async function try_catch_run() {
      try {
          const result = await asyncOperation();
          console.log(result)
      } catch (error) {
          console.error(error);  // 錯誤處理
      }
    }
    try_catch_run();

    編程中的錯誤,猶如我們人生中的不測風雲。通過 try...catch,我們可以捕捉到這些錯誤,正如在大雨中撐起一把傘。

  • Promise.all多個異步操作並行,猶如世事紛繁:

    // Promise.all
    async function fetchMultipleData() {
      const promise1 = Promise.resolve("數據1");
      const promise2 = Promise.resolve("數據2");
    
      const results = await Promise.all([promise1, promise2]);
      console.log(results); // ["數據1", "數據2"]
    }
    fetchMultipleData();

    然而,世事無常,多個異步任務往往會並行進行,正如我們在生活中處理的多項事務一樣。Promise.all 便是應對這一現實的法寶,它能並行執行多個任務,卻不因其中之一的失敗而放過所有問題。兩個異步操作,同時等待,若有一方失敗,便立即處理,這正如生活中,一件事辦砸,餘下的事情也可能隨之潰敗。

點擊體驗運行以上代碼

初次邂逅 axios

axios 她宛如紅蓋頭的新娘,正在等待着心上人掀開神秘。要不試試:node-typescript-playground(注:stackblitz.com 是一個在線的即時開發環境,它允許開發者在瀏覽器中創建、編輯和運行現代的Web應用)

  • get
    axios.get

    Axios.get<T = any, R = AxiosResponse<T, any>, D = any>(url: string, config?: AxiosRequestConfig<D>): Promise<R>

    泛型:T、R和D是泛型參數,它們允許用户自定義請求和響應的數據類型。

    T:表示請求返回的數據類型。
    R:表示響應對象的類型,它是一個AxiosResponse,包含請求返回的數據T和其他一些響應信息。
    D:表示請求發送的數據類型。
    函數參數:

    url:請求的URL地址,是一個字符串。
    config:這是一個可選參數,表示請求配置。它的類型是AxiosRequestConfig<D>,其中D是請求發送的數據類型。這個配置對象可以包含請求頭、超時時間、參數等信息。
    返回值:

    Promise<R>:函數返回一個Promise對象,它將解析為響應對象R。這意味着你可以使用.then()或async/await來處理請求的結果。
    以獲取指定用户名的 github 信息為例:

    // 引入依賴
    import axios from 'axios';
    
    // 認識 axios.get
    console.log(axios.get);
    // 運用 axios.get 獲取信息
    async function getUserInfo(username: string) {
    const { data } = await axios.get(`https://api.github.com/users/${username}`);
    return data;
    }
    getUserInfo('hu-qi').then((data) => {
    console.log(data);
    });

    axios.get gitub userinfo

  • post
    axios.post

    Axios.post<T = any, R = AxiosResponse<T, any>, D = any>(url: string, data?: D, config?: AxiosRequestConfig<D>): Promise<R>

    和 axios.get 大同小異,差別在於 data, data?: D:這是一個可選參數,表示請求發送的數據。它的類型是D,可以是任何類型。
    以axio.post實現發送消息到飛書機器人為例:

    // 運用 axios.post 提交信息
    async function sendHello(message: string = 'hello') {
    const { data } = await axios.post(
      'https://open.feishu.cn/open-apis/bot/v2/hook/8575490a-cf0e-4006-a64e-b7acef913844',
      {
        msg_type: 'text',
        content: {
          text: message,
        },
      }
    );
    return data;
    }
    sendHello(`Huqi, I'm comming!`)
    .then((data) => {
      console.log(data);
    })
    .catch((error) => {
      console.log('error', error);
    });

    axios.post sayHello

封裝 axios

周某人毫不自謙,AIGC 大時代下,客官只需敲擊封裝 axios,這事便成了。
封裝 axios,乃是開發中之常見需求,倘若處理得法,既可簡化代碼,亦能提高維護性,故值得慎思。以 https://github.com/zxwk1998/vue-admin-better為例。

其一,抽象共性,減輕重複之苦。axios作為一個HTTP請求庫,應用廣泛,然每每使用,常有共通之部分。如請求的基本配置、錯誤的統一處理,甚至是鑑權的頭部信息,皆可抽象為通用邏輯,置於封裝中。一言以蔽之,凡是重複且能複用者,皆當封裝之。點我.借鑑不是抄襲

其二,攔截器,乃是點睛之筆。axios自帶請求與響應攔截器,若能善加利用,便可在請求前後添加邏輯。例如,發請求前,自動附上用户Token;響應到來時,先做格式化處理,或依據狀態碼進行全局錯誤提示,如此,前端每處代碼皆無需再關心這些細節,專注於業務邏輯即可。此種攔截器之設,實為封裝精髓。點我,借鑑不是抄襲

其三,配置分離,靈活變通。開發環境與生產環境所用的baseURL常不同,若每次修改,實為煩冗,故將不同環境的配置抽離出來,根據環境變量動態加載,使得代碼更為靈活,且易於維護。點我,借鑑不是抄襲

其四,實例化axios,便於擴展。將axios實例化,既可封裝通用邏輯,又保留了後期擴展的餘地。例如,某些請求需要自定義的超時時間或特殊的Header,封裝時只需將這些配置參數傳入實例中,即可輕鬆應對。點我,借鑑不是抄襲

封裝其目的在於提升複用性與可維護性,世上本沒有路,走的人多了,也便成了路。封裝亦然,初見繁瑣,然為日後開發鋪平道路,實為不懈之功。

寫最後的話

其實,筆者一直很排斥 AIGC 來產出內容,觀點和破壞環境類似:不想留給後世一堆機器生成的財富。然鵝,AIGC 的大浪拍過來,沒有一個人是無辜的,這世界 AIGC 的含量會越來越高,也許未來百分百人工才是瑰寶。珍惜你我每一個親手敲擊或書寫的文字,珍重在DataWhale這段共學TypeScript的時光,後會有期!

參考資料

  • Datawhale Typescript教程5.1-異步處理
  • Datawhale Typescript教程5.2-get和post請求
  • Datawhale Typescript教程5.3-封裝axios
以上內容代碼為人工碼字演繹,部分文字由 ChatGPT 智能編寫創作

Add a new 评论

Some HTML is okay.