1

JavaScriptパケットが他のJavaScriptパケットを要求(同期ajax呼び出し)できるようにしたい:

// 2 sequential synchronous calls
framework.require('packet1'); // time1 ms
framework.require('packet2'); // time2 ms
// use packets

これらの2つのリクエストは、time1+time2ミリ秒で処理されます。したがって、別のアイデアがあります。これらのリクエストをそれぞれ非同期で作成しますが、一連のリクエスト全体が同期的に処理されることを保証します。

// 2 parallel asynchronous calls, synchronous in total
framework.require([
    'packet1', // time1 ms
    'packet2'  // time2 ms
]);
// use packets

私が理解している限り、これはもっと速いはずです。それでは、私の実装を見てみましょう。

framework = {
    require_counter:0,
    require: function(arr)
    {
        framework.require_counter = arr.length;

        var success = function(data, textStatus, jqXHR)
        {
            framework.require_counter -= 1;
        }
        var error = function(jqXHR, textStatus, errorThrown)
        {
            framework.require_counter -= 1;
            // some error notification
        }

        // asynchronous calls
        for (var i = 0; i < arr_js.length; i++)
            $.ajax({
                url: arr_js[i],
                success: success,
                error: error
            });

        // wait
        while (framework.require_counter > 0)
            framework.wait();

        // finally return
    }
}

最も難しい部分は、そのwait()関数を実装することです。JavaScriptはそれを提供しません。別の解決策を見つける必要があります。非同期のsetTimeout()は答えではありません。それが私の質問です:wait()関数を実装する方法は?または多分別の一般的な解決策がありますか?

私はこのアプローチを試しました:http://narayanraman.blogspot.com/2005/12/javascript-sleep-or-wait.html。たぶん、サーバーに依存しない、より「簡潔な」ソリューションを指摘するでしょう。

4

1 に答える 1

1

同期要求が本当に必要な場合は、通常、基盤となるAJAXメカニズムにそうするように指示できます。たとえば、jQueryでは、async 設定をfalseに設定します。XMLHttpRequestを使用する場合、3番目のパラメーターとしてfalseを渡します(これは、リンク先のブログ投稿でのopenラマンの実装方法です)。sleepただし、SJAXは、現在のブラウザでJSの実行をブロックするため、通常は悪いことです。継続渡しスタイルを使用して、実行する残りの計算を表す関数を渡すことをお勧めします。

framework = {
    require: function(urls, done)
    {
        function success(data, textStatus, jqXHR)
        {
            //...
        }
        function error(jqXHR, textStatus, errorThrown)
        {
            //...
        }

        urls.unshift('');
        function load() {
            urls.shift();
            if (urls.length) {
                $.ajax({
                    url: urls[0],
                    // here are some continuations
                    complete: load,
                    success: success,
                    error: error
                });
            } else {
                // here's a continuation invocation
                done();
            }
        }
    }
};

同期の代わりに、指定されたすべてのリソースがロードされたときに何らかのアクションを実行する必要がある場合は、アクションに継続を使用できますが、リソースのロードには使用できません。代わりに、イベント処理モデルを適用し、各ロードの完了を記録し、すべてのリソース要求が終了したときに依存アクションを呼び出します。

framework = {
    require: function(urls, done)
    {
        var remaining = urls.length;
        var failed=[];
        // The following implementation is vulnerable to race conditions.
        // Good thing JS isn't generally multithreaded. If (when) it is,
        // and if the browser doesn't offer some form of synchronization,
        // then Peterson's algorithm should work correctly if inefficiently.
        function success(data, textStatus, jqXHR) {
            if (!--remaining) { // critical section
                done(failed);
            }
        }
        function makeErrorHandler(url) {
            return function (jqXHR, textStatus, errorThrown) {
                failed.push(url);
                if (!--remaining) { // critical section
                    done(failed);
                }
            }
        }

        for (var i=0; i < urls.length; ++i) {
            $.ajax({
                url: urls[i],
                success: success,
                error: makeErrorHandler(urls[i])
            });
        }
    }
};
于 2011-02-17T01:52:37.000 に答える