中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

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

JS的Promise和Async是什么?

發布時間:2020-05-20 13:43:45 來源:億速云 閱讀:252 作者:鴿子 欄目:web開發

因為 JavaScript 是單線程語言,所以同步代碼一次只能執行一行。這就意味著同步代碼的運行時間超過瞬間的話,它將停止其余代碼的運行,直到完成運行為止。為了防止運行時間不確定的代碼阻止其他代碼的運行,我們需要使用異步代碼。

Promise

為此,我們可以在代碼中使用 Promise。Promise 表示流程運行時間不確定并且結果可能是成功或失敗的對象。在 JavaScript 中創建一個 promises,我們使用 Promise 對象的構造函數來創建 promise。Promise 構造函數接受一個擁有 resolve 和 reject 參數的執行函數。兩個參數也都是函數,它們讓我們可以回調 promise 完成(成功調用得到返回值)或者拒絕(返回錯誤值并標記 promise 失敗)。函數的返回值被忽略。因此,promise 只能返回 promise。

例如,我們在 JavaScript 定義一個承諾像下面的代碼:

const promise = new Promise((resolve, reject) => {  
  setTimeout(() => resolve('abc'), 1000);  
});

上面的代碼會創建一個一秒后返回 abc 的 promise。因為我們運行的 setTimeout 是在 executor 函數內一秒后返回值為 abc 的完成 promise,所以它是異步代碼。我們無法在 setTimeout 的回調函數中返回值 abc,因此我們必須調用 resolve('abc') 來獲取解析后的值。我們可以使用 then 函數來訪問已完成 promise 的返回值。then 函數接受一個回調函數,該回調函數將已完成的 promise 的返回值作為參數。你可以得到你想要的值。例如,我們可以這么做:

const promise = new Promise((resolve, reject) => {  
  setTimeout(() => resolve('abc'), 1000);  
});
promise.then((val) => {  
  console.log(val);  
})

當我們運行上方代碼,我們應該可以得到記錄 abc。正如我們看到的,promise 會在其完成后調用 resolve 函數時提供值。

一個 promise 有三種狀態。初始狀態,promise 既沒有成功也沒有失敗。完成狀態,意味著操作成功完成。或者是失敗狀態,意味著 promise 操作失敗。

一個掛起的 promise 可以通過返回值完成或者返回錯誤失敗。當 promise 完成后,then 函數將得到相應的返回值,并傳遞給 then 函數的回調函數來調用。如果 promise 失敗后,我們可以選擇使用 catch 函數來捕獲錯誤,該函數還可以傳遞給回調函數一個錯誤。then 和 catch 都返回一個 promise,因此它們可以一起鏈式使用。

例如,我們可以這么寫:

const promise = (num) => {  
  return new Promise((resolve, reject) => {  
    setTimeout(() => {  
      if (num === 1) {  
        resolve('resolved')  
      } else {  
        reject('rejected')  
      }  
    }, 1000);  
  });  
}
promise(1)  
  .then((val) => {  
    console.log(val);  
  })  
  .catch((error) => {  
    console.log(error);  
  })promise(2)  
  .then((val) => {  
    console.log(val);  
  })  
  .catch((error) => {  
    console.log(error);  
  })

在上面的代碼中,我們有一個函數 promise,它返回一個 JavaScript promise,其在 num 為 1 時以 resolved 值完成承諾,在 num 不為 1 時通過錯誤 rejected 拒絕承諾。因此我們運行:

promise(1)  
  .then((val) => {  
    console.log(val);  
  })  
  .catch((error) => {  
    console.log(error);  
  })

然后 then 函數運行,由于 num 為 1,promise(1) 函數調用會返回 promise 完成,并且解析后的值在 val 中是可用的。因此當我們運行 console.log(val),我們會得到 resolved。當我們運行下面的代碼:

promise(2)  
  .then((val) => {  
    console.log(val);  
  })  
  .catch((error) => {  
    console.log(error);  
  })

catch 會運行,因為 promise(2) 函數調用失敗返回 promise,并且被拒絕的錯誤值可用并設置為錯誤。因此我們運行 console.log(error) 會得到 rejected 輸出。

一個 JavaScript promise 對象有一下屬性:length 和 prototype。 length 是構造器參數的數量,其設置為 1,也總是只有一個。prototype 屬性表示 promise 對象的原型。

promise 還有一個 finally 方法無論 promise 完成還是失敗都運行的代碼。finally 方法接受一個回調函數作為參數,可以運行任何你想運行的代碼, 并且無論 promise 運行結果如何,都可以執行。例如,我們運行:

Promise.reject('error')  
  .then((value) => {  
    console.log(value);  
  })  
  .catch((error) => {  
    console.log(error);  
  })  
  .finally(() => {  
    console.log('finally runs');  
  })

然后我們得到 error 和 finally runs 的記錄,因為原始的 promise 得到 error 而拒絕。然后運行 finally 方法中的所有代碼。

使用 promise 最主要的好處是編寫的異步代碼,我們可以使用 promise 順序運行它們。為此,我們可以使用 then 函數鏈式 promise。then 函數在 promise 完成后接收一個回調函數并運行它。在 promise 拒絕后,它還接受第二個參數。鏈式使用 promise,我們必須將其第一個回調函數 then 函數返回另外一個 promise。如果我們不想將另外一個 promise 鏈接到現有的 promise,我們可以返回其他值,就像沒有一樣。我們可以返回一個值,該值將在下一個 then 函數中可獲取到。它還可以拋出一個錯誤。然后 then 返回的 promise 將被拒絕,并拋出錯誤。它還可以返回已經完成或拒絕的 promise,擋在其后鏈接的 then 函數時將獲得其完成后的值,或者 catch 函數的回調中獲得錯誤原因。

例如,我們可以這樣寫:

Promise.resolve(1)  
  .then(val => {  
    console.log(val);  
    return Promise.resolve(2)  
  })  
  .then(val => {  
    console.log(val);  
  })Promise.resolve(1)  
  .then(val => {  
    console.log(val);  
    return Promise.reject('error')  
  })  
  .then(val => {  
    console.log(val);  
  })  
  .catch(error => console.log(error));Promise.resolve(1)  
  .then(val => {  
    console.log(val);  
    throw new Error('error');  
  })  
  .then(val => {  
    console.log(val);  
  })  
  .catch(error => console.log(error));

在第一個例子中,我們鏈式調用 promise,并且都 resolve 一個值。所有的 promise 都準備返回為值。在第二個和最后一個例子中,我們拒絕了第二個 promise 或拋出一個錯誤。它們都做了同樣的事情。第二個 promise 被拒絕了,并且錯誤原因會被回調函數 catch 函數記錄下來。我們還可以鏈接掛起狀態的 promise,如下方代碼所示:

const promise1 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(1), 1000);  
});
const promise2 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(2), 1000);  
});
promise1  
  .then(val => {  
    console.log(val);  
    return promise2;  
  })  
  .then(val => {  
    console.log(val);  
  })  
  .catch(error => console.log(error));

回調函數 then 函數返回了 promise2,這是一個掛起狀態的 promise。

方法

JavaScript 的 promise 有以下方法。

Promise.all (可迭代對象)

Promise.all 接受一個可迭代對象,該對象允許我們在某些計算機上并行運行多個 promise,并在其他計算機上連續運行多個 promise。這對于運行多個不依賴于彼此的值的 promise 非常方便。它接受一個包含 promise 的列表 (通常是一個數組) 的可迭代對象,然后返回一個 Promise,這個 Promise 在可迭代對象中的 promise 被解析時解析。

例如,我們像下面這樣寫代碼,使用 Promise.all 來運行多個 promise:

const promise1 = Promise.resolve(1);  
const promise2 = 2;  
const promise3 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(3), 1000);  
});  
Promise.all([promise1, promise2, promise3])  
  .then((values) => {  
    console.log(values);  
  });

如果我們運行了上方的代碼,然后 console.log 應該會記錄下 [1,2,3]。如我們所見,只有所有的 promise 都完成后返回它的解析值。如果其中的拒絕了,我們不會得到任何解析值。相反,我們將得到由被拒絕的 promise 返回的任何錯誤值。它將會在第一個被拒絕的 promise 處停止,并且發送值給回調函數 catch 函數。例如,如果我們這樣:

const promise1 = Promise.resolve(1);  
const promise2 = Promise.reject(2);  
const promise3 = new Promise((resolve, reject) => {  
  setTimeout(() => reject(3), 1000);  
});  
Promise.all([promise1, promise2, promise3])  
  .then((values) => {  
    console.log(values);  
  })  
  .catch(error => {  
    console.log(error);  
  });

然后我們可以在回調函數 catch 函數的 console.log 中得到兩個記錄。

Promise.allSettled

Promise.allSettled 返回一個 promise,該 promise 的解析在所有的 promise 解析完或拒絕后。它接受帶有一組 promise 的可迭代對象,例如,一個 promise 數組。返回的 promise 的解析值是每個 promise 的最終狀態的數組。例如,假設我們有:

const promise1 = Promise.resolve(1);  
const promise2 = Promise.reject(2);  
const promise3 = new Promise((resolve, reject) => {  
  setTimeout(() => reject(3), 1000);  
});  
Promise.allSettled([promise1, promise2, promise3])  
  .then((values) => {  
    console.log(values);  
  })

若我們運行上方代碼,我們將獲得一個包含三個條目的數組,每個條目都是一個對象,該對象有已經完成 promise 的 status 和 value 屬性以及被拒絕的 promise 的 status 和 reason 屬性。例如,上面的代碼會記錄 {status: “fulfilled”, value: 1},{status: “rejected”, reason: 2},{status: “rejected”, reason: 3}。 fulfilled 狀態記錄的是成功的 promise,rejected 狀態為被拒絕的 promise。

Promise.race

Promise.race 方法返回一個 promise,該 promise 會解析首先完成的 promise 的解析值。它接受一個帶有 promise 集合的可迭代對象,例如,一個 promise 數組。如果傳入的可迭代對象為空,則返回的 promise 將一直掛起。若可迭代對象包含一個或多個非 promise 值或者已經完成的 promise,Promise.race 將會返回這些條目中的第一個。例如,我們有:

const promise1 = Promise.resolve(1);  
const promise2 = Promise.resolve(2);  
const promise3 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(3), 1000);  
});  
Promise.race([promise1, promise2, promise3])  
  .then((values) => {  
    console.log(values);  
  })

然后我們看到 1 會被記錄 。那是因為 promise1 是第一個被解析的,那是因為它是在下一行運行之前就被解析了。同樣,如果我們的數組中有一個非 promise 值作為參數進行傳入,如下代碼所示:

const promise1 = 1;  
const promise2 = Promise.resolve(2);  
const promise3 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(3), 1000);  
});  
Promise.race([promise1, promise2, promise3])  
  .then((values) => {  
    console.log(values);  
  })

然后我們會得到相同的記錄,因為它是我們傳遞給 Promise.race 方法的數組中的非 promise 值。同步代碼始終運行在異步代碼之前,而不論同步代碼在哪里。如果我們有:

const promise1 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(1), 2000);  
});
const promise2 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(2), 1000);  
});
const promise3 = 3;  
Promise.race([promise1, promise2, promise3])  
  .then((values) => {  
    console.log(values);  
  })

然后我們記錄下 3,因為 setTimeout 將回調函數放入隊列中以便稍后運行,所以它將比同步代碼更晚執行。

最后,如果我們有:

const promise1 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(1), 2000);  
}); 
const promise2 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(2), 1000);  
});
Promise.race([promise1, promise2])  
  .then((values) => {  
    console.log(values);  
  })

然后我們在控制臺中得到記錄 2,因為在一秒解析的 promise 要比兩秒解析的 promise 更早解析。

Promise.reject

Promise.reject 返回一個因某種原因拒絕的 promise。拒絕帶有 Error 的實例對象的 promise 非常有用。例如,如果我們有以下代碼:

Promise.reject(new Error('rejected'))  
  .then((value) => {  
    console.log(value);  
  })  
  .catch((error) => {  
    console.log(error);  
  })

然后我們得到 rejected 記錄。

Promise.resolve

Promise.resolve 返回一個已解析為傳入 resolve 函數參數的值的 promise。我們也可以傳遞一個帶有 then 屬性的對象,它的值是 promise 的回調函數。如果該值具有 then 方法,則將使用 then 函數完成 promise。也就是說,then 函數值的第一個參數與 resolve 相同,以及第二個參數與 reject 相同。例如,我們可以編寫如下代碼:

Promise.resolve(1)  
  .then((value) => {  
    console.log(value);  
  })

然后我們得到 1 記錄,因為 1 是我們傳遞給 resolve 函數來返后具有解析值 1 的承諾的值。

如果我們傳入的對象內部帶有 then 方法,如下代碼所示:

Promise.resolve({  
    then(resolve, reject) {  
      resolve(1);  
    }  
  })  
  .then((value) => {  
    console.log(value);  
  })

然后我們得到記錄的值 1。這是因為 Promise.resolve 函數將運行 then 函數,設置為 “then” 屬性的函數的 “resolve” 參數將被假定為承諾中稱為 “resolve” 函數的函數。并將該函數的 resolve 參數設置為 then 屬性可以看作 promise 中一個叫做 resolve 函數。如果我們將傳入 then 中的對象替換為 inject 函數,然后我們就可以得到被拒絕的 promise。代碼如下所示:

Promise.resolve({  
    then(resolve, reject) {  
      reject('error');  
    }  
  })  
  .then((value) => {  
    console.log(value);  
  })  
  .catch((error) => {  
    console.log(error);  
  })

在上面的代碼中,我們會得到 error 記錄,這是因為 promise 被拒絕了。

Async 和 Await

使用 async 和 await,我們可以縮短 promise 代碼。使用 async 和 await 之前前,我們必須得用 then 函數并且在 then 函數中放入回調函數作為所有的參數。這就使得我們有很多 promise 時代碼冗長至極。相反,我們可以使用 async 和 await 語法來替代 then 函數以及相關回調。例如,我們可將以下代碼縮短為:

const promise1 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(1), 2000);  
});
const promise2 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(2), 1000);  
});
promise1  
  .then((val1) => {  
    console.log(val1);  
    return promise2;  
  })  
  .then((val2) => {  
    console.log(val2);  
  })

寫成:

const promise1 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(1), 2000);  
});  
const promise2 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(2), 1000);  
});
(async () => {  
  const val1 = await promise1;  
  console.log(val1)  
  const val2 = await promise2;  
  console.log(val2)  
})()

我們使用 await 來替換 then 和回調函數。然后,我們就可以將每個 promise 的解析值分配為變量。注意,如果我們為 promise 代碼使用 await,那么我們必須像上例那樣添加 async 到函數簽名中。為了捕獲錯誤,我們使用 catch 子句取代鏈式 catch 函數。另外,我們沒有在底部鏈式調用 finally 函數以在 promise 結束時運行代碼,而是在 catch 子句后使用 finally 子句。

例如,我們可以這樣寫:

const promise1 = new Promise((resolve, reject) => {  
  setTimeout(() => resolve(1), 2000);  
});  
const promise2 = new Promise((resolve, reject) => {  
  setTimeout(() => reject('error'), 1000);  
});
(async () => {  
  try {  
    const val1 = await promise1;  
    console.log(val1)  
    const val2 = await promise2;  
    console.log(val2)  
  } catch (error) {  
    console.log(error)  
  } finally {  
    console.log('finally runs');  
  }})()

在上面的代碼中,我們獲得了分配給變量的 promise 的解析值,而不是在 then 函數的回調中獲取值,例如在 const response = await promise1 上面的一行。另外,我們使用 try...catch...finally 塊來捕獲被拒絕的 promise 的錯誤,以及 finally 子句替代 finally 函數,其無論 promise 執行結果如何,該代碼都可以運行。

想其他使用 promise 的函數一樣,async 函數始終返回 promise,并且不能返回其他任何東西。在上面的示例中,我們證明了與使用帶有回調函數作為參數傳遞的 then 函數相比,我們可以更短的方式使用 promise。

結束語

使用 promise,讓我們編寫異步代碼更容易。promise 是表示一個處理的運行時間不確定并且結果會成功也會失敗的對象。在 JavaScript 中創建一個 promises,我們使用 Promise 對象,該對象是用于創建 promise 的構造函數。

Promise 構造函數接受一個擁有 resolve 和 reject 參數的執行函數。兩個參數都是函數,它們讓我們可以回調 promise 完成(成功調用得到返回值)或者拒絕(返回錯誤值并標記 promise 失敗)。 The 函數的返回值被忽略。因此,promise 只能返回 promise。

因為 promise 返回 promise,所以 promise 是可鏈式調用。promise 的 then 函數可以拋出一個錯誤,返回解析值,或者其他 promise(掛起、已完成或已拒絕的 promise)。

向AI問一下細節

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

AI

自治县| 云和县| 叙永县| 虞城县| 高雄县| 舟山市| 西丰县| 高邮市| 南皮县| 会宁县| 娄底市| 姜堰市| 赫章县| 新巴尔虎右旗| 谢通门县| 罗平县| 黑河市| 宾阳县| 七台河市| 项城市| 麻江县| 平潭县| 攀枝花市| 固镇县| 中方县| 潞西市| 堆龙德庆县| 高邮市| 敖汉旗| 新河县| 辽源市| 北宁市| 化隆| 西林县| 无锡市| 淮南市| 康保县| 靖远县| 建宁县| 永胜县| 鱼台县|