JavaScript で約束のキャンセルをマスターする
ロザリオ・デ・キアラ作✏️
JavaScript では、Promises は非同期操作を処理するための強力なツールであり、特に UI 関連のイベントで役立ちます。これらは、すぐには利用できないかもしれないが、将来のある時点で解決される値を表します。
Promise により、開発者は API 呼び出し、ユーザー インタラクション、アニメーションなどのタスクを処理する際に、よりクリーンで管理しやすいコードを作成できるようになります (または許可される必要があります)。 Promise では、.then()、.catch()、.finally() などのメソッドを使用することで、成功とエラーのシナリオをより直感的に処理できるようになり、悪名高い「コールバック地獄」を回避できます。
この記事では、新しい (2024 年 3 月) Promise.withResolvers() メソッドを使用します。このメソッドを使用すると、新しい Promise と 2 つの関数 (1 つは Promise を解決するための関数) の 3 つを含むオブジェクトを返すことで、よりクリーンでシンプルなコードを作成できます。これは最近の更新であるため、この記事の例を実行するには最新の Node ランタイム (v>22) が必要です。
新旧の JavaScript Promise メソッドの比較
次の 2 つの機能的に同等のコード部分では、Promise を解決または拒否するメソッドを割り当てる古いアプローチと新しいアプローチを比較できます。
let resolve, reject; const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); Math.random() > 0.5 ? resolve("ok") : reject("not ok");
上記のコードでは、Promise の最も伝統的な使用方法がわかります。新しい Promise オブジェクトをインスタンス化し、コンストラクターで、resolve と拒否の 2 つの関数を割り当てる必要があります。これらの関数は、次のときに呼び出されます。必要です。
次のコード スニペットでは、同じコード部分が新しい Promise.withResolvers() メソッドで書き直されており、より単純になっています。
const { promise, resolve, reject } = Promise.withResolvers(); Math.random() > 0.5 ? resolve("ok") : reject("not ok");
ここでは、新しいアプローチがどのように機能するかを確認できます。これは Promise を返します。これに対して .then() メソッドと 2 つの関数、resolve および拒否を呼び出すことができます。
Promise への従来のアプローチでは、作成ロジックとイベント処理ロジックが 1 つの関数内にカプセル化されているため、複数の条件やコードの異なる部分で Promise を解決または拒否する必要がある場合に制限が生じる可能性があります。
対照的に、Promise.withResolvers() は、Promise の作成を解決ロジックから分離することで柔軟性を高め、複雑な条件や複数のイベントの管理に適しています。ただし、単純なユースケースの場合、標準的な Promise パターンに慣れている人にとっては、従来の方法の方がシンプルで馴染みやすいかもしれません。
実際の例: API の呼び出し
今度は、より現実的な例で新しいアプローチをテストできるようになりました。以下のコードでは、API 呼び出しの簡単な例を確認できます。
function fetchData(url) { return new Promise((resolve, reject) => { fetch(url) .then(response => { // Check if the response is okay (status 200-299) if (response.ok) { return response.json(); // Parse JSON if response is okay } else { // Reject the promise if the response is not okay reject(new Error('API Invocation failed')); } }) .then(data => { // Resolve the promise with the data resolve(data); }) .catch(error => { // Catch and reject the promise if there is a network error reject(error); }); }); } // Example usage const apiURL = '<ADD HERE YOU API ENDPOINT>'; fetchData(apiURL) .then(data => { // Handle the resolved data console.log('Data received:', data); }) .catch(error => { // Handle any errors that occurred console.error('Error occurred:', error); });
fetchData 関数は、URL を取得し、フェッチ API を使用して API 呼び出しを処理する Promise を返すように設計されています。応答ステータスが 200 ~ 299 の範囲内にあるかどうかを確認して応答を処理し、成功を示します。
成功した場合、応答は JSON として解析され、結果のデータで Promise が解決されます。応答が成功しなかった場合、Promise は拒否され、適切なエラー メッセージが表示されます。さらに、この関数にはネットワーク エラーを検出するためのエラー処理が含まれており、そのようなエラーが発生した場合は Promise を拒否します。
この例では、この関数の使用方法を示し、.then() ブロックで解決されたデータを管理し、.catch() ブロックを使用してエラーを処理し、成功したデータ取得とエラーの両方が適切に管理されるようにする方法を示しています。
以下のコードでは、新しい Promise.withResolvers() メソッドを使用して fetchData() 関数を書き直します。
function fetchData(url) { const { promise, resolve, reject } = Promise.withResolvers(); fetch(url) .then(response => { // Check if the response is okay (status 200-299) if (response.ok) { return response.json(); // Parse JSON if response is okay } else { // Reject the promise if the response is not okay reject(new Error('API Invocation failed')); } }) .then(data => { // Resolve the promise with the data resolve(data); }) .catch(error => { // Catch and reject the promise if there is a network error reject(error); }); return promise; }
ご覧のとおり、上記のコードはより読みやすく、オブジェクト Promise の役割は明確です。fetchData 関数は、成功するか失敗する Promise を返し、それぞれの場合に適切なメソッドを呼び出します。 。上記のコードは、api.invocation.{old|new}.js.
という名前のリポジトリにあります。約束のキャンセル
次のコードは、Promise キャンセル メソッドを実装する方法を検討します。ご存知かもしれませんが、JavaScript では Promise をキャンセルできません。 Promise は非同期操作の結果を表し、作成後に解決または拒否するように設計されており、キャンセルする組み込みメカニズムはありません。
この制限は、Promise に定義された状態遷移プロセスがあるために発生します。それらは保留中として開始され、一旦解決されると状態を変更できません。これらは、操作自体を制御するのではなく、操作の結果をカプセル化することを目的としています。つまり、基礎となるプロセスに影響を与えたり、キャンセルしたりすることはできません。この設計の選択により、Promise はシンプルになり、操作の最終的な結果を表すことに重点が置かれます。
const cancellablePromise = () => { const { promise, resolve, reject } = Promise.withResolvers(); promise.cancel = () => { reject("the promise got cancelled"); }; return promise; };
In the code above, you can see the object named cancellablePromise, which is a promise with an additional cancel() method that, as you can see, simply forces the invocation of the reject method. This is just syntactic sugar and does not cancel a JavaScript Promise, though it may help in writing clearer code.
An alternative approach is to use an AbortController and AbortSignal, which can be tied to the underlying operation (e.g., an HTTP request) to cancel it when needed. From the documentation, you can see that the AbortController and AbortSignal approach is a more expressive implementation of what we implemented in the code above: once the AbortSignal is invoked, the promise just gets rejected.
Another approach is to use reactive programming libraries like RxJS, which offers an implementation of the Observable pattern, a more sophisticated control over async data streams, including cancellation capabilities.
A comparison between Observables and Promises
When speaking about practical use cases, Promises are well-suited for handling single asynchronous operations, such as fetching data from an API. In contrast, Observables are ideal for managing streams of data, such as user input, WebSocket events, or HTTP responses, where multiple values may be emitted over time.
We already clarified that once initiated, Promises cannot be canceled, whereas Observables allow for cancellation by unsubscribing from the stream. The general idea is that, with Observables, you have an explicit structure of the possible interaction with the object:
- You create an Observable, and then all the Observables can subscribe to it
- The Observable carries out its work, changing state and emitting events. All the Observers will receive the updates – this is the main difference with Promises. A Promise can be resolved just once while the Observables can keep emitting events as long as there are Observers
- Once the Observer is not interested in the events from the Observables, it can unsubscribe, freeing resources
This is demonstrated in the code below:
import { Observable } from 'rxjs'; const observable = new Observable(subscriber => { subscriber.next(1); subscriber.next(2); subscriber.next(3); subscriber.complete(); }); const observer = observable.subscribe({ next(x) { console.log('Received value:', x); }, complete() { console.log('Observable completed'); } }); observer.unsubscribe();
This code cannot be rewritten with Promises because the Observable returns three values while a Promise can only be resolved once.
To experiment further with the unsubscribe method, we can add another Observer that will use the takeWhile() method: it will let the Observer wait for values to match a specific condition; in the code below, for example, it keeps receiving events from the Observable while the value is not 2:
import { Observable, takeWhile } from 'rxjs'; const observable = new Observable(subscriber => { subscriber.next(1); subscriber.next(2); subscriber.next(3); subscriber.complete(); }); const observer1 = observable.subscribe({ next(x) { console.log('Received by 1 value:', x); }, complete() { console.log('Observable 1 completed'); } }); const observer2 = observable.pipe( takeWhile(value => value != "2") ).subscribe(value => console.log('Received by 2 value:', value));
In the code above, observer1 is the same as we have already seen: it will just subscribe and keep receiving all the events from the Observable. The second one, observer2, will receive elements from the Observable while the condition is matched. In this case, this means when the value is different from 2.
From the execution, you can see how the two different mechanisms work:
$ node observable.mjs Received by 1 value: 1 Received by 1 value: 2 Received by 1 value: 3 Observable 1 completed Received by 2 value: 1 $
Conclusion
In this article, we investigated the new mechanism to allocate a Promise in JavaScript and laid out some of the possible ways to cancel a Promise before its completion. We also compared Promises with Observable objects, which not only offer the features of Promises but extend them by allowing multiple emissions of events and a proper mechanism for unsubscribing.
LogRocket: Debug JavaScript errors more easily by understanding the context
Debugging code is always a tedious task. But the more you understand your errors, the easier it is to fix them.
LogRocket allows you to understand these errors in new and unique ways. Our frontend monitoring solution tracks user engagement with your JavaScript frontends to give you the ability to see exactly what the user did that led to an error.
LogRocket records console logs, page load times, stack traces, slow network requests/responses with headers + bodies, browser metadata, and custom logs. Understanding the impact of your JavaScript code will never be easier!
Try it for free.
以上がJavaScript で約束のキャンセルをマスターするの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

Web開発におけるJavaScriptの主な用途には、クライアントの相互作用、フォーム検証、非同期通信が含まれます。 1)DOM操作による動的なコンテンツの更新とユーザーインタラクション。 2)ユーザーエクスペリエンスを改善するためにデータを提出する前に、クライアントの検証が実行されます。 3)サーバーとのリフレッシュレス通信は、AJAXテクノロジーを通じて達成されます。

現実世界でのJavaScriptのアプリケーションには、フロントエンドとバックエンドの開発が含まれます。 1)DOM操作とイベント処理を含むTODOリストアプリケーションを構築して、フロントエンドアプリケーションを表示します。 2)node.jsを介してRestfulapiを構築し、バックエンドアプリケーションをデモンストレーションします。

JavaScriptエンジンが内部的にどのように機能するかを理解することは、開発者にとってより効率的なコードの作成とパフォーマンスのボトルネックと最適化戦略の理解に役立つためです。 1)エンジンのワークフローには、3つの段階が含まれます。解析、コンパイル、実行。 2)実行プロセス中、エンジンはインラインキャッシュや非表示クラスなどの動的最適化を実行します。 3)ベストプラクティスには、グローバル変数の避け、ループの最適化、constとletsの使用、閉鎖の過度の使用の回避が含まれます。

PythonとJavaScriptには、コミュニティ、ライブラリ、リソースの観点から、独自の利点と短所があります。 1)Pythonコミュニティはフレンドリーで初心者に適していますが、フロントエンドの開発リソースはJavaScriptほど豊富ではありません。 2)Pythonはデータサイエンスおよび機械学習ライブラリで強力ですが、JavaScriptはフロントエンド開発ライブラリとフレームワークで優れています。 3)どちらも豊富な学習リソースを持っていますが、Pythonは公式文書から始めるのに適していますが、JavaScriptはMDNWebDocsにより優れています。選択は、プロジェクトのニーズと個人的な関心に基づいている必要があります。

開発環境におけるPythonとJavaScriptの両方の選択が重要です。 1)Pythonの開発環境には、Pycharm、Jupyternotebook、Anacondaが含まれます。これらは、データサイエンスと迅速なプロトタイピングに適しています。 2)JavaScriptの開発環境には、フロントエンドおよびバックエンド開発に適したnode.js、vscode、およびwebpackが含まれます。プロジェクトのニーズに応じて適切なツールを選択すると、開発効率とプロジェクトの成功率が向上する可能性があります。

CとCは、主に通訳者とJITコンパイラを実装するために使用されるJavaScriptエンジンで重要な役割を果たします。 1)cは、JavaScriptソースコードを解析し、抽象的な構文ツリーを生成するために使用されます。 2)Cは、Bytecodeの生成と実行を担当します。 3)Cは、JITコンパイラを実装し、実行時にホットスポットコードを最適化およびコンパイルし、JavaScriptの実行効率を大幅に改善します。

Pythonはデータサイエンスと自動化により適していますが、JavaScriptはフロントエンドとフルスタックの開発により適しています。 1. Pythonは、データ処理とモデリングのためにNumpyやPandasなどのライブラリを使用して、データサイエンスと機械学習でうまく機能します。 2。Pythonは、自動化とスクリプトにおいて簡潔で効率的です。 3. JavaScriptはフロントエンド開発に不可欠であり、動的なWebページと単一ページアプリケーションの構築に使用されます。 4. JavaScriptは、node.jsを通じてバックエンド開発において役割を果たし、フルスタック開発をサポートします。
