JS の Promise に中止関数を追加する方法

JS の Promise に中止関数を追加する方法

概要

Promise には、保留、解決、拒否の 3 つの状態しかありません。非同期 Promise が発行されると、待機 (保留) した後は、最終的に成功または失敗することしかできず、途中でキャンセル (中止) することはできません。

Promise に中止機能を提供するには、次の 2 つの方法があります。

  • 手動で中止を実装します。キャンセルがトリガーされた後、非同期で返されたデータは直接破棄されます (手動実装は比較的安全です)
  • ネイティブ メソッド AbortController を使用してリクエストを中断します (実験的なメソッド、互換性あり、IE ではサポートされていません)

手動でabortメソッドを実装するには2つのモードがあります。どちらもpromiseインターフェースを使用して間接的に実装します。

プロミスレースメソッド

PromiseWithAbort = function(promise){
    _abort = null とします。
    Pabort = new Promise((res,rej)=>{とする
      _abort = function(reason ='abort !'){
        console.warn(理由);
        rej(理由);
      }
    });

    race = Promise.race([promise,Pabort]) とします。
    レースを中止します。
    コンソールにログ出力します。
    復帰レース;
  }

p1 = new Promise(res=>{
   タイムアウトを設定します(()=>{
      res('p1 成功');
   },2000)
})

testP = PromiseWithAbort(p1); とします。

testP.then(res=>{
  console.log('成功:',res);
},エラー=>{
  console.log('エラー:',エラー);
})

テストPを中止します。

// 結果: 拒否: 中止!

約束の再パッケージ化

クラスPromiseWithAbort {
    コンストラクタ(fn){
      _abort = null とします。
      _p = new Promise((res,rej)=>{ とする
        fn.call(null,res,rej);
        _abort = function(error='abort'){ rej(error); }
      })

      _p.abort = _abort;
      _p を返します。
    }
  } 


testP = new PromiseWithAbort((res,rej)=>{ とする
    タイムアウトを設定する(() => {
      レス(1);
    },1000);
  });

 testP.then(r=>{
    コンソールにログ出力します。
  },r=>{
    console.log('rej:',r);
  });

  テストPを中止します。
//結果: rej: 中止

中止コントローラ

(これは DOM 仕様に属する実験的な機能であり、一部のブラウザではまだ開発中です。) AbortController インターフェイスは、必要に応じて 1 つ以上の DOM 要求を中止できるコントローラ オブジェクトを表します。

// フェッチ要求を中断する let controller = new AbortController();
  シグナルを controller.signal とします。

 fetch('https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally',{signal}).then(r=>{
    コンソールログr;
  });

  コントローラーを中止します。
// 結果: キャッチされませんでした (promise 内) DOMException: ユーザーがリクエストを中止しました。
//Promise を中断する
クラスPromiseWithAbortController {
  コンストラクタ(fn,{シグナル}){
    if (シグナル && signal.aborted) {
      Promise.reject(新しいDOMException('Aborted','AbortError'))を返します。
    }

    _p = new Promise((resolve,reject)=>{ とする
      fn.call(null、解決、拒否);
      if(シグナル){
        シグナル.addEventListener('abort',()=>{
          拒否(新しいDOMException('Aborted','AbortError'));
        })
      }
    });

    _p を返します。
  }
}
コントローラーを新しいAbortController()にします。
  シグナルを controller.signal とします。
testP2 = new PromiseWithAbortController((r,j)=>{ とする
  タイムアウトを設定する(() => {
    r('成功');
  }, 1000);
}、{信号});

testP2.then(r=>{
    コンソールにログ出力します。
  },r=>{
    console.log('rej:',r);
  });

  コントローラーを中止します。
  // 結果: rej: DOMException: 中止

Axiosプラグインにはキャンセル機能が付属しています

//1. ソーストークンを使用する
CancelToken は axios.CancelToken に置き換えられます。
const ソース = CancelToken.source();

axios.get('/user/12345', {
  キャンセルトークン: ソース.token
}).catch(関数(スロー) {
  もし(axios.isCancel(スロー)){
    console.log('リクエストがキャンセルされました', throwed.message);
  } それ以外 {
    // エラーを処理する
  }
});

axios.post('/user/12345', {
  名前: '新しい名前'
}, {
  キャンセルトークン: ソース.token
})

// リクエストをキャンセルします(メッセージパラメータはオプションです)
source.cancel('ユーザーによって操作がキャンセルされました。');

//2. 送信関数を通じて
CancelToken は axios.CancelToken に置き換えられます。
キャンセルする;

axios.get('/user/12345', {
  キャンセルトークン: 新しいキャンセルトークン(関数executor(c) {
    // 実行関数はキャンセル関数をパラメータとして受け取ります
    キャンセル = c;
  })
});

// リクエストをキャンセルする
キャンセル();

//メイン: 同じトークンを使用するリクエストはまとめてキャンセルできます

Axios は現在のプロジェクトで最も頻繁に使用されているため、リクエストをキャンセルしても問題ありません。互換性上の理由から、DOM 指定の AbortController は推奨されません。自分で実装する必要がある場合は、この記事の最初の 2 つの方法 (Promise 競合方法と Promise 再パッケージ化方法) の方が安全です。

以上がJSがpromiseにabort関数を追加する方法の詳細です。JSの詳細については、123WORDPRESS.COMの他の関連記事にも注目してください。

以下もご興味があるかもしれません:
  • JavaScript Promise の徹底解説
  • JavaScript における Promise の詳細な説明
  • フロントエンドJavaScriptの約束
  • JS 9 Promise 面接の質問
  • JavaScriptのPromiseを徹底的に理解する

<<:  Tomcat クラスローダーの実装方法とサンプルコード

>>:  MySQL を解凍してインストールおよび完全に削除する方法の詳細なグラフィック説明

推薦する

Linux クラウド サーバーに JDK と Tomcat をインストールするための詳細な手順 (推奨)

JDKをダウンロードしてインストールするステップ 1: まず、公式 Web サイト http://...

10 HTML テーブル関連タグ

実際、多くの人が「テーブルは絶対に使用すべきではないと聞いたことがある」と言いますが、これは絶対に間...

Mysql general_log をクリーンアップする方法の概要

方法1: グローバル general_log を 'OFF' に設定します。 テーブ...

1 つの記事で MySQL のプリコンパイルを理解する

1. プリコンパイルの利点私たちは皆、プリコンパイル機能を備えた JDBC の PreparedSt...

CSS3 のテキストとフォントの新しい設定

テキストシャドウテキストシャドウ: 水平オフセット 垂直オフセット ぼかし色互換性: IE10+ &...

MySQLの認可コマンド grant の使い方のまとめ

MySQL 認証コマンド grant の使用方法:この記事の例は MySQL 5.0 以降で実行され...

Ubuntu mysqlログイン名とパスワードを表示および変更し、phpmyadminをインストールする

MySQLをインストールした後、ターミナルでmysql -u root -pと入力してEnterを押...

Zabbix と bat スクリプトを組み合わせて複数のアプリケーションの状態を監視する方法

シナリオシミュレーション:国内企業の中には、重要な業務をサポートするために特定のウィンドウ プログラ...

HTML タイトルに二重引用符を追加する方法

<a href="https://www.jb51.net/" title...

Youku 動画から 30 秒の広告コードを削除する 2 つの方法

誰もがこんな気持ちになったことがあると思います。30 秒の広告が入った動画を見ると、とても不快に感じ...

node.jsのインストールとHbuilderXの設定の詳細な説明

npm インストールチュートリアル: 1. Node.jsインストールパッケージをダウンロードする公...

Linux centos7 環境での MySQL インストール チュートリアル

Linux centos7 環境に MySQL をインストールする手順の詳細な紹介MySQLをインス...

MySQL チュートリアル データ定義言語 DDL の例 詳細な説明

目次1. SQL言語の基本機能の紹介2. データ定義言語の目的3. データベースの作成と破棄4. デ...

MySQL binlog ログを開く方法

binlog は、すべての mysql dml 操作を記録するバイナリ ログ ファイルです。 bin...