<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Promise:為什么沒有取消?

          共 5067字,需瀏覽 11分鐘

           ·

          2024-06-24 08:00

          在JavaScript中,Promise是用于處理異步操作的對象,它代表一個異步操作的最終完成(或失敗)及其結(jié)果值。然而,JavaScript的Promise并不提供內(nèi)置的取消(cancel)機(jī)制。

          Promise是經(jīng)過了深思熟慮,才不自帶取消功能的!!!

          這篇文章,將圍繞著設(shè)計的哲學(xué),以及從狀態(tài)機(jī)的角度,解釋為什么不需要cancel

          即使如此,文章最后部分,還是會提供一些方法,來實現(xiàn)一下cancle

          設(shè)計的哲學(xué)

          設(shè)計理念

          • Promise的設(shè)計初衷是為了簡化回調(diào)函數(shù)的使用,使得處理異步操作的代碼更加簡潔和可讀。其設(shè)計重點在于處理異步操作的成功和失敗,而不是控制操作的生命周期
          • 取消機(jī)制會引入復(fù)雜性,尤其是對于依賴于多個Promise的情況,例如Promise.allPromise.race。如果某個Promise被取消,其影響可能會傳遞給其他依賴于它的Promise,導(dǎo)致意外的行為和難以調(diào)試的問題。

          資源管理

          • 異步操作通常涉及到外部資源,如網(wǎng)絡(luò)請求、定時器等。Promise取消機(jī)制需要能夠正確管理和釋放這些資源。實現(xiàn)一個通用且可靠的資源管理機(jī)制非常復(fù)雜,并且可能因不同的資源類型而異。

          取消語義不明確

          • 如果一個Promise可以被取消,那么需要明確如何處理其已完成的狀態(tài)。特別是,處理已經(jīng)部分完成或即將完成的操作,可能會導(dǎo)致不一致的狀態(tài)。

          狀態(tài)機(jī):簡單就是美

          Promise的狀態(tài)機(jī)

          在輸入一個狀態(tài)時,只得到一個固定的狀態(tài)。

          一個Promise可以被看作是一個簡單的狀態(tài)機(jī),它有以下幾種狀態(tài):

          1. Pending(進(jìn)行中) :初始狀態(tài),表示異步操作尚未完成。
          2. Fulfilled(已完成) :表示異步操作成功完成,并返回了一個值。
          3. Rejected(已拒絕) :表示異步操作失敗,并返回了一個原因(錯誤)。

          狀態(tài)轉(zhuǎn)換規(guī)則如下:

          • Pending狀態(tài)可以轉(zhuǎn)換到Fulfilled狀態(tài)。
          • Pending狀態(tài)可以轉(zhuǎn)換到Rejected狀態(tài)。
          • 一旦轉(zhuǎn)換到FulfilledRejected狀態(tài),Promise的狀態(tài)就不可再改變。

          取消功能的復(fù)雜性

          引入取消功能意味著需要增加一個新的狀態(tài)——“Cancelled(已取消)”。這會使?fàn)顟B(tài)機(jī)的設(shè)計變得更加復(fù)雜,因為需要考慮更多的狀態(tài)轉(zhuǎn)換和邊界情況

          如果我們引入“Cancelled”狀態(tài),狀態(tài)機(jī)的狀態(tài)和轉(zhuǎn)換規(guī)則將變成:

          1. Pending(進(jìn)行中)

            • 可以轉(zhuǎn)換到Fulfilled
            • 可以轉(zhuǎn)換到Rejected
            • 可以轉(zhuǎn)換到Cancelled
          1. Fulfilled(已完成) :狀態(tài)不可變。
          2. Rejected(已拒絕) :狀態(tài)不可變。
          3. Cancelled(已取消) :狀態(tài)不可變。

          這種增加的復(fù)雜性會導(dǎo)致以下問題:

          • 狀態(tài)轉(zhuǎn)換沖突:需要明確地處理在Pending狀態(tài)下多次轉(zhuǎn)換的情況。例如,如果一個PromisePending狀態(tài)下同時嘗試轉(zhuǎn)換到FulfilledCancelled,應(yīng)該優(yōu)先處理哪一個?
          • 副作用處理:許多異步操作(如網(wǎng)絡(luò)請求、文件讀寫等)具有副作用。取消這些操作需要確保所有相關(guān)的資源都被正確地清理,這不僅增加了實現(xiàn)的復(fù)雜性,還可能導(dǎo)致不一致的狀態(tài)。
          • 鏈?zhǔn)讲僮?/strong>:Promise通常被鏈?zhǔn)秸{(diào)用( .then().catch() )。如果一個中間的Promise被取消,如何處理后續(xù)鏈?zhǔn)讲僮饕彩且粋€難題。例如,Promise.allPromise.race的行為如何改變?

          如何實現(xiàn)取消功能

          盡管標(biāo)準(zhǔn)的Promise沒有內(nèi)置的取消功能,可以通過一些方法來實現(xiàn)類似的功能。例如,使用AbortController來取消網(wǎng)絡(luò)請求,或者使用自定義的Promise包裝器來支持取消。

          使用AbortController

          對于Fetch API,可以使用AbortController來取消請求:

          const controller = new AbortController();
          const signal = controller.signal;

          fetch('https://www.baidu.com', { signal })
            .then(response => response)
            .then(data => console.log(data))
            .catch(err => {
              if (err.name === 'AbortError') {
                console.log('Fetch aborted');
              } else {
                console.error('Fetch error:', err);
              }
            });

          // 取消請求
          controller.abort();

          自定義Promise包裝器

          也可以創(chuàng)建一個支持取消的自定義Promise包裝器:

          class CancellablePromise {
            constructor(executor) {
              this._hasCanceled = false;
              
              this._promise = new Promise((resolve, reject) => {
                executor(
                  value => this._hasCanceled ? reject({ canceledtrue }) : resolve(value),
                  reason => this._hasCanceled ? reject({ canceledtrue }) : reject(reason)
                );
              });
            }
            
            cancel() {
              this._hasCanceled = true;
            }

            then(onFulfilled, onRejected) {
              return this._promise.then(onFulfilled, onRejected);
            }

            catch(onRejected) {
              return this._promise.catch(onRejected);
            }
          }

          // 使用自定義的CancellablePromise
          const cancellablePromise = new CancellablePromise((resolve, reject) => {
            setTimeout(() => resolve('Completed!'), 1000);
          });

          cancellablePromise.then(
            result => console.log(result),
            err => {
              if (err.canceled) {
                console.log('Promise was canceled');
              } else {
                console.error('Promise error:', err);
              }
            }
          );

          // 取消Promise
          cancellablePromise.cancel();

          雖然標(biāo)準(zhǔn)的Promise沒有內(nèi)置取消功能,但可以通過這些方法來實現(xiàn)取消邏輯,根據(jù)實際需求選擇合適的方案。

          結(jié)語

          雖然JavaScript的Promise沒有內(nèi)置取消功能,但這并不意味著我們無法實現(xiàn)取消功能。通過理解Promise的設(shè)計哲學(xué)和狀態(tài)機(jī)模型,我們可以更好地掌握其使用方法,并通過巧妙的編程技巧實現(xiàn)我們需要的功能

          本文轉(zhuǎn)載于稀土掘金技術(shù)社區(qū)——德瑪西亞大寶劍之力

          原文:https://juejin.cn/post/7373986431850872869


             “分享、點贊在看” 支持一下

          瀏覽 51
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  精品久久精品 | 国产一级黄片在线播放 | 一二三区久在线视频 | 久久免费视频1 | 五月丁香福利 |