溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JS中Promise?axios請求結(jié)果.then()指的是什么意思

發(fā)布時間:2022-01-25 10:47:37 來源:億速云 閱讀:575 作者:小新 欄目:開發(fā)技術

這篇文章主要為大家展示了“JS中Promise axios請求結(jié)果.then()指的是什么意思”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“JS中Promise axios請求結(jié)果.then()指的是什么意思”這篇文章吧。

    Promise 是JS中一種處理異步操作的機制,在現(xiàn)在的前端代碼中使用頻率很高。Promise 這個詞可能有點眼生,但你肯定見過 axios.get(...).then(res => {...});用于異步請求的 axios 返回的就是一個 Promise 對象。

    平時一直在代碼中 .then() .catch() 地寫來寫去,終于決定要認真學一學這個 Promise 到底是怎么回事,希望這篇學習筆記也能幫到你。

    Promise 對象

    一個 Promise 對象表示一個異步操作的執(zhí)行結(jié)果,包括狀態(tài)(成功/失敗)和值(成功返回值/錯誤原因)。一個 Promise 在創(chuàng)建的時候異步操作可能還沒執(zhí)行完成,通過持有這個 Promise 對象,可以在未來異步操作完成的時候?qū)Y(jié)果進行相應操作。

    Promise 對象的狀態(tài)

    這里有幾個常用的名詞,用來表示 Promise 對象當前的具體狀態(tài):

    Pending 待定:剛創(chuàng)建時的初始狀態(tài),還沒有確定執(zhí)行結(jié)果

    Fulfilled 已兌現(xiàn):異步操作執(zhí)行成功,并返回一個值

    Rejected 已拒絕:異步操作執(zhí)行失敗,并返回一個錯誤原因

    Settled 已敲定 / Resolved 已決議:“待定”狀態(tài)的反面,都表示異步操作已經(jīng)執(zhí)行完成,即已兌現(xiàn)已拒絕

    JS中Promise?axios請求結(jié)果.then()指的是什么意思

    回調(diào)函數(shù)

    如果完全不關心異步操作的執(zhí)行結(jié)果,那就把它放在那自己執(zhí)行就可以了;但通常情況下我們總是要對操作執(zhí)行的結(jié)果進行后續(xù)處理的,例如更改頁面上的數(shù)據(jù)顯示、錯誤處理等。但由于異步操作不知道什么時候可以執(zhí)行完成,就出現(xiàn)了“回調(diào)函數(shù)”的概念,意思就是等到異步操作處理結(jié)束了,再回過頭來調(diào)用這個函數(shù)來對執(zhí)行結(jié)果進行處理。

    傳統(tǒng)做法是,在執(zhí)行異步操作的時候就把回調(diào)函數(shù)作為參數(shù)傳進去,比如最常見的:

    setTimeout(function(){
        console.log("成功!");
    }, 250);

    setTimeout() 函數(shù)是最常見的異步函數(shù)之一,眾所周知它的作用就是在指定時間后執(zhí)行指定代碼。仔細看就會發(fā)現(xiàn),setTimeout()函數(shù)接收兩個參數(shù),第二個參數(shù)是等待時間,而第一個參數(shù)就是回調(diào)函數(shù),即等待指定的時間之后要回來調(diào)用這個函數(shù)。

    很顯然這種傳參的做法有很多不方便的地方,比如把對結(jié)果的后續(xù)處理和異步操作本身耦合在了一起,以及著名的回調(diào)地獄:

    doSomething(function(result) {
      doSomethingElse(result, function(newResult) {
        doThirdThing(newResult, function(finalResult) {
          console.log('Got the final result: ' + finalResult);
        }, failureCallback);
      }, failureCallback);
    }, failureCallback);

    Promise.then() 綁定回調(diào)函數(shù)

    有了 Promise 之后,就能把回調(diào)和異步操作本身分開了。無論一個 Promise 對象當前是否已經(jīng)執(zhí)行完畢,我們都能在它上面綁定回調(diào)函數(shù),并且保證回調(diào)函數(shù)被執(zhí)行;這就是喜聞樂見的 then() 方法。

    p.then(onFulfilled[, onRejected]);
    p.then(value => {
      // fulfillment
    }, reason => {
      // rejection
    });

    then() 方法的語法很簡單,有兩個可選參數(shù),分別代表當 Promise 的狀態(tài)變?yōu)槌晒Γ╢ulfilled)和失?。╮ejected)時所使用的回調(diào)函數(shù)。

    如果只想綁定 onRejected(即失敗時的錯誤處理函數(shù)),下面兩種寫法完全等價,第二種是第一種的簡寫形式。

    p.then(null, failureCallback);
    p.catch(failureCallback);

    使用 Promise:鏈式調(diào)用

    如果只是用 then 來綁定回調(diào)函數(shù),那并不能解決回調(diào)地獄的問題。然而很妙的地方來了:Promise 支持鏈式調(diào)用

    doSomething().then(function(result) {
      return doSomethingElse(result);
    })
    .then(function(newResult) {
      return doThirdThing(newResult);
    })
    .then(function(finalResult) {
      console.log('Got the final result: ' + finalResult);
    })
    .catch(failureCallback);

    鏈式調(diào)用的實現(xiàn)

    能做到鏈式調(diào)用的魔法來自 then() 方法:它會在執(zhí)行相應的回調(diào)函數(shù)之后,返回一個新的 Promise 對象,并且插入 Promise 鏈的當前位置。

    這里稍微有點繞,容易把回調(diào)函數(shù)等同于 then() 方法本身。實際上成功/失敗的回調(diào)函數(shù)只是 then() 的參數(shù)而已;而實際執(zhí)行 then() 的時候,它會先根據(jù) promise 的狀態(tài)調(diào)用相應的回調(diào)函數(shù),再根據(jù)回調(diào)函數(shù)的執(zhí)行結(jié)果生成一個新的 Promise 對象并返回;具體的對應規(guī)則如下:

    回調(diào)函數(shù)執(zhí)行情況then() 返回的 Promise 對象
    返回值 return x;fulfilled 狀態(tài),參數(shù)為 x
    直接返回 return; / 無 return 語句fulfilled 狀態(tài),參數(shù)為 undefined
    拋出錯誤 throw err;rejected 狀態(tài),參數(shù)為 err
    返回已決議的 Promise狀態(tài)和參數(shù)與返回的 Promise 一致
    返回未定的 Promise未定的 Promise,回調(diào)參數(shù)與返回的相同

    下面這個例子中,初始 Promise 的狀態(tài)為已拒絕,然后第一個 then() 調(diào)用了綁定的 onRejected,返回了狀態(tài)為 fulfilled 的新 Promise 對象,并傳遞給了鏈中的下一個 then():

    Promise.reject()
      .then(() => 99, () => 42) // 調(diào)用 onRejected(return 42;),表格中的第一種情況
      .then(solution => console.log('Resolved with ' + solution)); // Resolved with 42

    同時,你可能還記得 then() 的參數(shù)定義,兩個回調(diào)函數(shù)都是可選的;如果沒有傳入對應的回調(diào)函數(shù),then() 會直接把原 promise 的終態(tài)返回,不做額外處理。

    錯誤處理

    遇到異常拋出(被拒絕的 promise)時,瀏覽器會順著 Promise 鏈尋找下一個 onRejected 回調(diào)函數(shù)(經(jīng)常被簡寫為 .catch()),并跳過中間的 onFulfilled 回調(diào)函數(shù)。這種執(zhí)行邏輯與同步代碼中的 try-catch 執(zhí)行過程非常相似:

    // 異步 Promise
    doSomething()
    .then(result => doSomethingElse(result))
    .then(newResult => doThirdThing(newResult))
    .then(finalResult => console.log(`Got the final result: ${finalResult}`))
    .catch(failureCallback);
    
    // 同步
    try {
      let result = syncDoSomething();
      let newResult = syncDoSomethingElse(result);
      let finalResult = syncDoThirdThing(newResult);
      console.log(`Got the final result: ${finalResult}`);
    } catch(error) {
      failureCallback(error);
    }

    一個具體的例子:

    Promise.resolve()
    .then(() => {
        throw new Error('出錯');
        console.log('a');
    })
    .then(() => {
        console.log('b');
    })
    .catch(() => {
        console.log('c');
    })
    .then(() => {
        console.log('d');
    });
    
    // 輸出結(jié)果:
    // "c"
    // "d"

    常見錯誤

    doSomething().then(function(result) {
      doSomethingElse(result) // 沒有返回 Promise 以及沒有必要的嵌套 Promise
      .then(newResult => doThirdThing(newResult));
    }).then(() => doFourthThing());
    // 最后,是沒有使用 catch 終止 Promise 調(diào)用鏈,可能導致沒有捕獲的異常

    上面這個例子在 Promise 中進行了嵌套,但沒有將嵌套的 Promise 對象返回,因此doFourthThing() 不會等待 doSomethingElse()或 doThirdThing() 完成,而是并行運行;并且如果有傳入?yún)?shù),接收到的會是 undefined 而不是 doThirdThing() 的執(zhí)行結(jié)果。

    正確的寫法應該是:

    注:箭頭函數(shù) () => x 是 () => { return x; } 的簡寫,即返回了新的 Promise 對象

    doSomething()
    .then(function(result) {
      return doSomethingElse(result);
    })
    .then(newResult => doThirdThing(newResult))
    .then(() => doFourthThing())
    .catch(error => console.log(error));

    創(chuàng)建 Promise 對象

    如果要執(zhí)行的異步操作沒有返回 Promise 對象,可以用 new 和構(gòu)造器創(chuàng)建自己的 promise。構(gòu)造器的兩個參數(shù)的作用是在異步操作成功/失敗時,轉(zhuǎn)換 Promise 對象的狀態(tài)并傳遞對應參數(shù)。

    const myFirstPromise = new Promise((resolve, reject) => {
      // 做一些異步操作,最終會調(diào)用下面兩者之一:
      // resolve(someValue); // fulfilled
      // reject("failure reason"); // rejected
    });
    
    // 一個例子
    function myAsyncFunction(url) {
      return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open("GET", url);
        xhr.onload = () => resolve(xhr.responseText);
        xhr.onerror = () => reject(xhr.statusText);
        xhr.send();
      });
    };

    Promise 其他靜態(tài)方法

    創(chuàng)建已決議的 Promise 對象

    Promise.resolve(value) 和 Promise.reject(reason) 方法分別返回一個已經(jīng)成功/失敗的 Promise 對象。

    const p1 = new Promise((resolve, reject) => {
      resolve();
    });
    const p2 = Promise.resolve();

    如果 resolve(value) 的參數(shù)是帶有 then() 方法的 Promise 對象,函數(shù)將返回其自帶 then() 方法的執(zhí)行結(jié)果;如果參數(shù)為空或是基本類型,返回的Promise對象與在 then() 方法中 return 對應值的結(jié)果一致,參見上文表格?;谶@樣的特性, resolve(value) 方法可以用于將不確定是否為 Promise 對象的 value 值統(tǒng)一為 Promise。

    多個 Promise 對象

    Promise.all(iterable)

    • 參數(shù)列表中的所有的 promises 都成功時,返回一個 fulfilled 的 Promise 對象,參數(shù)值是所有 promises 成功返回值的列表(順序不變)

    • 如果任何一個 promise 失敗,立即返回一個 rejected 的 Promise 對象,參數(shù)是這個失敗 promise 的錯誤信息

    Promise.all([func1(), func2(), func3()])
    .then(([result1, result2, result3]) => { /* use result1, result2 and result3 */ });

    Promise.allSettled(iterable)列表中所有 promises 都已敲定后返回一個promise,并帶有一個對象數(shù)組,對應每個promise 的結(jié)果。

    Promise.any(iterable)當列表中的任意一個 promise 成功時,立即返回這個 promise 的值。

    Promise.race(iterable)當列表中任意一個 promise 成功或失敗時,立即返回該 promise 對象的執(zhí)行結(jié)果。

    一個綜合例子(使用 setTimeout 模擬異步操作):

    // 創(chuàng)造一個狀態(tài)為 fulfilled,參數(shù)為"foo"的 Promise 對象
    Promise.resolve("foo")
      .then(function(string) {	// string: "foo"
        // 返回狀態(tài)為 fulfilled,參數(shù)為"foobar"的對象
        return new Promise(function(resolve, reject) {
          setTimeout(function() {
            string += 'bar';
            resolve(string);
          }, 1);
        });
      })
      .then(function(string) {	// string: "foobar"
        setTimeout(function() {
          string += 'baz';
          console.log(string);
        }, 1)
        // 返回值"foobar"
        return string;
      })
      .then(function(string) {	// string: "foobar"
        console.log("Last Then");
        console.log(string);
      });
    
    // 輸出結(jié)果:
    // Last Then
    // foobar
    // foobarbaz(由第二個 then 中的 setTimeout 輸出)

    以上是“JS中Promise axios請求結(jié)果.then()指的是什么意思”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業(yè)資訊頻道!

    向AI問一下細節(jié)

    免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI