3

要求されたファイルのサイズが、ajax呼び出しの応答にかかる時間に影響することに気づきました。したがって、さまざまなサイズのファイルに対して3つのajax GETリクエストを実行すると、それらは任意の順序で到着する可能性があります。私がやりたいのは、ファイルをDOMに追加するときに順序を保証することです。

A1->A2->A3を起動するときにキューシステムを設定するにはどうすればよいですか。A1->A2->A3の順で追加されることを保証できます。

たとえば、A2がA1の前に到着するとします。A1の到着とロードを待ってアクションを実行したいと思います。

1つのアイデアは、時限コールバックを使用してステータスチェッカーを作成することです。

// pseudo-code
function check(ready, fund) {
    // check ready some how
    if (ready) {
        func();
    } else {
        setTimeout(function () {
            check(ready, fund);
        }, 1); // check every msec
    }
}

しかし、リソースがロードされるまで、1ミリ秒ごとに同じ関数を起動するため、これはリソースを大量に消費する方法のように見えます。

これはこの問題を完了するための正しい道ですか?

4

4 に答える 4

4

1ミリ秒のタイミングのコールバックを使用するステータスチェッカー-しかし、これはリソースを大量に消費する方法のようです。これはこの問題を完了するための正しい道ですか?

いいえ。Promisesをご覧ください。そうすれば、次のように簡単に定式化できます。

var a1 = getPromiseForAjaxResult(ressource1url);
var a2 = getPromiseForAjaxResult(ressource2url);
var a3 = getPromiseForAjaxResult(ressource3url);

a1.then(function(res) {
    append(res);
    return a2;
}).then(function(res) {
    append(res);
    return a3;
}).then(append);

たとえば、jQueryの.ajax関数はこれを実装します。

于 2013-03-26T17:36:48.747 に答える
2

あなたはこのようなことを試すことができます:

var resourceData = {};
var resourcesLoaded = 0;

function loadResource(resource, callback) {
    var xhr = new XMLHttpRequest();
    xhr.onload = function() {
        var state = this.readyState;
        var responseCode = request.status;

        if(state == this.DONE && responseCode == 200) {
            callback(resource, this.responseText);
        }
    };

    xhr.open("get", resource, true);
    xhr.send();
}

//Assuming that resources is an array of path names
function loadResources(resources) {
    for(var i = 0; i < resources.length; i++) {
        loadResource(resources[i], function(resource, responseText) {

            //Store the data of the resource in to the resourceData map,
            //using the resource name as the key. Then increment the
            //resource counter.
            resourceData[resource] = responseText;
            resourcesLoaded++;

            //If the number of resources that we have loaded is equal
            //to the total number of resources, it means that we have
            //all our resources.
            if(resourcesLoaded === resources.length) {
                //Manipulate the data in the order that you desire.
                //Everything you need is inside resourceData, keyed
                //by the resource url. 
                ...
                ...
            }                    
        });
    }
}

特定のコンポーネント(特定のJSファイルなど)を他のコンポーネントよりも先にロードして実行する必要がある場合は、次のようにAJAXリクエストをキューに入れることができます。

function loadResource(resource, callback) {
    var xhr = new XMLHttpRequest();
    xhr.onload = function() {
        var state = this.readyState;
        var responseCode = request.status;

        if(state == this.DONE && responseCode == 200) {
            //Do whatever you need to do with this.responseText
            ...
            ...

            callback();
        }
    };

    xhr.open("get", resource, true);
    xhr.send();
}

function run() {
    var resources = [
        "path/to/some/resource.html",
        "path/to/some/other/resource.html",
        ...
        "http://example.org/path/to/remote/resource.html"
    ];

    //Function that sequentially loads the resources, so that the next resource 
    //will not be loaded until first one has finished loading. I accomplish
    //this by calling the function itself in the callback to the loadResource 
    //function. This function is not truly recursive since the callback 
    //invocation (even though it is the function itself) is an independent call 
    //and therefore will not be part of the original callstack.
    function load(i) {
        if (i < resources.length) {
            loadResource(resources[i], function () {
                load(++i);
            });
        }
    }
    load(0);
}

このように、前のファイルのロードが完了するまで、次のファイルはロードされません。

サードパーティのライブラリを使用できない場合は、私のソリューションを使用できます。ただし、 Bergi が提案したことを実行し、 Promisesを使用すると、おそらくあなたの生活ははるかに楽になります。

于 2013-03-26T17:29:40.050 に答える
1

check()ミリ秒ごとに呼び出す必要はありません。xhrで実行するだけonreadystatechangeです。コードをもう少し提供していただければ、さらに説明できます。

于 2013-03-26T17:29:48.253 に答える
1

実行する関数のキューがあり、それぞれが実行前に前の結果が完了したことを確認します。

var remoteResults[] 

function requestRemoteResouse(index, fetchFunction) {
  // the argument fetchFunction is a function that fetches the remote content
  // once the content is ready it call the passed in function with the result.
  fetchFunction(
    function(result) { 
      // add the remote result to the list of results
      remoteResults[index] = result
      // write as many results as ready.
      writeResultsWhenReady(index);
    });
}

function writeResults(index) {
  var i;
  // Execute all functions at least once
  for(i = 0; i < remoteResults.length; i++) {
    if(!remoteResults[i]) {
      return;
    }
    // Call the function that is the ith result
    // This will modify the dom.
    remoteResults[i]();
    // Blank the result to ensure we don't double execute
    // Store a function so we can do a simple boolean check.
    remoteResults[i] = function(){}; 
  }
}

requestRemoteResouse(0, [Function to fetch the first resouse]);
requestRemoteResouse(1, [Function to fetch the second resouse]);
requestRemoteResouse(2, [Function to fetch the thrid resouse]);

簡単にするために、これは現在O(n ^ 2)であることに注意してください。hasRenderedプロパティを持つremoteResultsのすべてのインデックスにオブジェクトを格納すると、高速になりますが、より複雑になります。次に、まだ発生していない結果またはレンダリングされた結果が見つかるまで、スキャンバックするだけです。

于 2013-03-26T17:51:53.807 に答える