web-dev-qa-db-ja.com

スレッドなしでJavascriptでPromiseを実装する方法

最近、AngularJSとJQueryで実装されているPromiseの概念を見てきました。

以下のコードのようにJavaでFutureの実装を確認しましたが、これには言語/プラットフォームにスレッドプールの概念が存在する必要があります。ただし、Javascriptにはそのようなスレッド化の概念はありません。 JavascriptのPromiseはどのように実装されますか?

public class Futures1 {

    private static final ExecutorService pool = Executors
            .newFixedThreadPool(10);

    public static void main(String[] args) {

        Future<String> contentsFuture = null;
        try {
            contentsFuture = startDownloading(new URL("http://www.example.com"));
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        // other computation
        try {
            final String contents = contentsFuture.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }

    }

    public static Future<String> startDownloading(final URL url) {
        return pool.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                try (InputStream input = url.openStream()) {
                    return IOUtils.toString(input, StandardCharsets.UTF_8);
                }
            }
        });
    }
}
37
Madhur Ahuja

非同期操作の管理を支援するためのプロミスが考案されました。そのためにプロミス自体にスレッドは必要ありません。それらは本質的に非同期操作のブックキーピングを提供するオブジェクトです-状態遷移の状態フラグ、結果値、リスナーを保持します。これらはすべて、通常のシングルスレッドのJavascriptで簡単に実行できるものです。

したがって、非同期操作がある限り(それらの操作が実装されていても)、Promiseの恩恵を受けることができ、それらを実装するためにスレッドは必要ありません。

Javaコードは、通常のタスクを別のスレッドで実行するのに役立つコードです(同期操作に非同期タイプの動作を提供するため)。それは、Promiseが行うことではありません。したがって、環境にすでに非同期操作がある場合、promiseを使用するためにこのタイプのコードは必要ありません。

JavaScriptでの非同期の例は、関心を登録するほとんどすべてのものであり、実際のイベントは将来のある時点で発生し、そのイベントが発生する前に他のコードを実行できます。ブラウザのJavaScript環境では、これにはsetTimeout()、キーボードイベント、マウスイベント、ajax完了コールバックなどが含まれます。これらはすべて非同期イベントです。それらに関心を登録します(イベントリスナーを登録するか、コールバックを関数に渡します)。 Javascript実装の内部では、これらの非同期イベントを機能させるスレッドが存在する可能性がありますが、非同期機能が存在するためにこれらのスレッドをプログラマーに直接公開する必要はありません。たとえば、JavaScriptが他のJavascriptの実行中にバックグラウンドでajax呼び出しを実行する方法については、 この投稿 を参照してください。知っておく必要があるのは、コールバック関数が将来、不確定な時期に呼び出されることです。

したがって、JavaScriptでは、promiseを使用して、環境に既に存在する非同期操作を管理します。非同期でないものを非同期にするためには使用されません(そのためにはスレッドが必要です)。

Promise自体は、既存の非同期操作を監視するために使用される監視ツールにすぎないことに注意してください。 .then()またはsetTimeout()またはsetImmediate()などの組み込みAPIで実装できるnextTick()を除いて、実際にはプロミスは非同期ではありません。プロミスは独自のネイティブコードやスレッドを必要としません。実際、必要に応じて、promise実装をプレーンなシングルスレッドのJavascriptで記述できます。

39
jfriend00

JavaScriptレイヤーの下にあるブラウザーで作成されたネイティブコードは、スレッドを適切に実装する傾向があります。結局のところ、必要なのはそれだけです。 JavaScriptで実際の計算作業を実行するためにプロミスが必要になる傾向はありますが(ワーカーによって簡単になります)、外部リソースをロードし、完了時にコールバックを取得するためです。 JS Promiseは、「image.onLoad」などの関数にコールバックを割り当て、別の関数に通知するかどうかを確認するだけです。

ホーガンは、イベントベースのプログラミングという点で、それを最もよく要約しているかもしれません。

3
Katana314