1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Promise:為什么沒有取消?

        共 6477字,需瀏覽 13分鐘

         ·

        2024-07-16 09:15

        點(diǎn)擊上方 前端Q,關(guān)注公眾號(hào)

        回復(fù)加群,加入前端Q技術(shù)交流群

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

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

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

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

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

        設(shè)計(jì)理念

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

        資源管理

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

        取消語義不明確

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

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

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

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

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

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

        狀態(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ù)雜性

        引入取消功能意味著需要增加一個(gè)新的狀態(tài)——“Cancelled(已取消)”。這會(huì)使?fàn)顟B(tài)機(jī)的設(shè)計(jì)變得更加復(fù)雜,因?yàn)樾枰紤]更多的狀態(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ù)雜性會(huì)導(dǎo)致以下問題:

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

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

        盡管標(biāo)準(zhǔn)的Promise沒有內(nèi)置的取消功能,可以通過一些方法來實(shí)現(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)建一個(gè)支持取消的自定義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)置取消功能,但可以通過這些方法來實(shí)現(xiàn)取消邏輯,根據(jù)實(shí)際需求選擇合適的方案。

        結(jié)語

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

        本文轉(zhuǎn)載于掘金-德瑪西亞大寶劍之力

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


        往期推薦


        基于wujie的解決方案來簡單聊聊微前端
        “Vue 之父”最新采訪:我是第一個(gè)吃螃蟹的人
        通過可視化徹底搞懂 Promise執(zhí)行邏輯

        最后


        • 歡迎加我微信,拉你進(jìn)技術(shù)群,長期交流學(xué)習(xí)...

        • 歡迎關(guān)注「前端Q」,認(rèn)真學(xué)前端,做個(gè)專業(yè)的技術(shù)人...

        點(diǎn)個(gè)在看支持我吧

        瀏覽 125
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

          <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            毛片导航 | 日韩精品三级 | 美女久久久久久 | 理论在线中文字幕无码 | 五月天婷婷综合在线播放 | 国产3p露脸普通话对白 | 被邻居侵犯调教成了里番acg | 文中字幕一区二区三区视频播放 | 成人爽a毛片一区二区免费 | 欧美日韩在线视频免费观看 |