0

SO で同様の問題を検索しました (例: Chrome が <div> を非表示にした後に再描画せず、Chrome/Mac で DOM の再描画/更新を強制する) が、どの質問も私の問題の解決策を教えてくれませんでした。私はモデム設定パネル、タブ付きのウェブページを書いています。すべてのタブには、ルーターの構成パネルと同じように、いくつかの設定があります。

構成の保存 (ユーザーが [保存] ボタンをクリックしたときに実行) には数秒かかります (私の組み込みプラットフォームはスピード キングではありません)。そのため、通常は非表示ですが、必要なときに表示される特別な PLEASE WAIT ウィンドウ (正確には div) を配置することにしました。ユーザーを落ち着かせるために:-)。

Firefox ではすべて正常に動作します。[保存] をクリックすると、PLEASE WAIT div が表示され、POST メソッドを使用して構成が保存されます。ただし、Chrome 26 および Chromium 25 では、構成が保存されるまで div は表示されませんSaveConfiguration構成を保存する PHP スクリプトを実行した後の関数でわかるように、アラートが表示されます。これは、Chrome で PLEASE WAIT div が表示される場所です。Chrome はページを再描画していないようですが、すぐに POST スクリプトの起動を開始します。誰かが同様の問題を抱えていて、この問題を解決する方法はありますか?

以下は私のコードの断片です。私が何をしているかの手がかりを与える可能性のある関数のみを提供しました。それが役立つ場合は、さらにコードを投稿できます。

function showLoadingScreen(yes)
{
    if(yes)
    {
        document.getElementById("loadingtext").innerHTML="Please wait...";
        document.getElementById("loading_overlay").style.display="block";
        document.getElementById("loading_window").style.display="block";
    }
    else
    {
        document.getElementById("loading_overlay").style.display="none";
        document.getElementById("loading_window").style.display="none";
    }
}

function postDataSync(url, params)
{
    var XMLHttpRequestObject = false;
    if (window.XMLHttpRequest) 
    {
        XMLHttpRequestObject = new XMLHttpRequest();
    } else 
        if (window.ActiveXObject) 
        {
            XMLHttpRequestObject = new
            ActiveXObject("Microsoft.XMLHttp");
        }
    if(XMLHttpRequestObject) 
    {
        XMLHttpRequestObject.open("POST", url, false);
        XMLHttpRequestObject.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
        XMLHttpRequestObject.send(params);
        {
            if (XMLHttpRequestObject.readyState == 4 &&
            XMLHttpRequestObject.status == 200) 
            {
                var result = XMLHttpRequestObject.responseText;
                delete XMLHttpRequestObject;
                XMLHttpRequestObject = null;
                return result;
            }
        }
    }
    return '';  
}

function SaveConfiguration()
{
    var errors=checkForm();
    if(errors!="")
    {
        printError("Can't save configuration because there are errors in current tab:<br><br>"+errors);
        return;
    }
    showLoadingScreen(true);
    saveTab();
    var retval=postDataSync('actions/saveconf3.php','');
    alert("Settings saved. The modem is now being reconfigured.");
    document.location = "http://" + retval;
}
4

2 に答える 2

2

リクエスト中にJavaScriptの実行が停止することを意味する非同期ではなく、同期的にajaxを使用しています。修正するには、次の変更を行います。

XMLHttpRequestObject.open("POST", url, true);

リクエストが完了した後、動作にコールバックを使用する必要があります。このようなもの:

    function postDataSync(url, params, success)
    {
        var XMLHttpRequestObject = false;
        if (window.XMLHttpRequest) 
        {
            XMLHttpRequestObject = new XMLHttpRequest();
        } else 
            if (window.ActiveXObject) 
            {
                XMLHttpRequestObject = new
                ActiveXObject("Microsoft.XMLHttp");
            }
        if(XMLHttpRequestObject) 
        {
            XMLHttpRequestObject.open("POST", url, true);
            XMLHttpRequestObject.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
            XMLHttpRequestObject.send(params);
            XMLHttpRequestObject.onreadystatechange = function() {
                if (XMLHttpRequestObject.readyState == 4 &&
                XMLHttpRequestObject.status == 200) 
                {

    var result = XMLHttpRequestObject.responseText;
                    delete XMLHttpRequestObject;
                    XMLHttpRequestObject = null;
                    if (typeof success === 'function') success(result);
                }
            }
        }
        return '';  
    }

function SaveConfiguration()
{
    var errors=checkForm();
    if(errors!="")
    {
        printError("Can't save configuration because there are errors in current tab:<br><br>"+errors);
        return;
    }
    showLoadingScreen(true);
    saveTab();
    postDataSync('actions/saveconf3.php','', saveComplete);
}

function saveComplete(result) {
  showLoadingScreen(false);
  alert("Settings saved. The modem is now being reconfigured.");
  document.location = "http://" + result;
}
于 2013-05-16T14:54:12.077 に答える
1

大量の同期コード (実際には、既にメモリ内にある数百または数千のオブジェクトに対する操作、または数十億桁の pi の計算) を使用setTimeoutして、ブラウザーがレンダリング タスクに追いつく時間を与えることができます。setTimeoutタスクごとに呼び出すか、長時間実行されるタスクがある場合は、最初にバッチに分割する必要があります。ただし、これにはかなりのリファクタリングが必要です。これは、すべてのタスクを渡せる関数として表す必要があるためですsetTimeout.

XMLHTTPRequest を同期的に使用することはありません。

setTimeout(fn, 0)「インクリメンタル」レンダリングがトリガーされない場合は、機能するまでより高い値を試してください。一部のブラウザーでは、場合によってはジョブ間で 100ms の値を使用する必要があったと思います (どのブラウザーかは覚えていません)。

60 fps または 30 fps を達成したい場合は、ブラウザにさらに早く屈服する必要があるかもしれません。次に、各タスクを 16 ミリ秒または 33 ミリ秒未満に抑える必要があります。(古いタイプの)スマートフォンなど、遅いハードウェアでは非常にきつくなります。次に、 の代わりにsetTimeout、可能な場合は を使用するのが最適requestAnimationFrameです。

于 2013-05-16T15:18:35.207 に答える