戻る前に、Ajax呼び出しが完了するのをjQueryに待機させるにはどうすればよいですか?


243

ログインが必要なサーバー側の機能があります。ユーザーがログインしている場合、関数は成功すると1を返します。そうでない場合、関数はログインページを返します。

AjaxとjQueryを使用して関数を呼び出したいのですが。私が行うことは、クリック機能が適用された通常のリンクを使用してリクエストを送信することです。ユーザーがログインしていないか、関数が失敗した場合、Ajax呼び出しがtrueを返すようにして、hrefがトリガーされるようにします。

ただし、次のコードを使用すると、Ajax呼び出しが完了する前に関数が終了します。

ユーザーをログインページに適切にリダイレクトするにはどうすればよいですか?

$(".my_link").click(
    function(){
    $.ajax({
        url: $(this).attr('href'),
        type: 'GET',
        cache: false,
        timeout: 30000,
        error: function(){
            return true;
        },
        success: function(msg){ 
            if (parseFloat(msg)){
                return false;
            } else {
                return true;
            }
        }
    });
});

2
古いスレッドである可能性がありますが、@ kofifusが指摘するように、非同期をfalseに設定することは悪い設計であり、「タイムアウトなどは処理されません」。この簡略化されたソリューションを試してみてください-stackoverflow.com/a/11576418/6937841
Shan

回答:


355

$.ajax()関数をすぐに返さない場合は、asyncオプションをfalse次のように設定します。

$(".my_link").click(
    function(){
    $.ajax({
        url: $(this).attr('href'),
        type: 'GET',
        async: false,
        cache: false,
        timeout: 30000,
        error: function(){
            return true;
        },
        success: function(msg){ 
            if (parseFloat(msg)){
                return false;
            } else {
                return true;
            }
        }
    });
});

しかし、これはAJAXのポイントに反することになると思います。また、errorおよびsuccess関数で応答を処理する必要があります。これらの関数は、サーバーから応答を受け取ったときにのみ呼び出されます。


10
私の意見では、良い習慣を伝えることは判断ではなく、ここでStackOverflowに関する最良の答えのいくつかの印です。
センペロス2011

68
決して使用しないでくださいasync: false信頼性の低いネットワークI / Oを待機している間、ブラウザーのイベントループがハングします。常により良い方法があります。この場合、リンクのターゲットは、ユーザーセッションとログインページへの302を確認できます。
マシュー

3
テストにasync: falseは、非常に役立ちます。
Jarrett

4
@マシュー本当に?ユーザーを他のページに送信したり更新したりする前に、非同期でajaxを送信する代わりの方法は何ですか?
NoBugs 2014年

2
asyncwith value falseは、ほとんどのブラウザの使用例で廃止されました。新しいバージョンのブラウザーでは例外がスローされる場合があります。xhr.spec.whatwg.org/#sync-warningを参照してください(jQueryを使用するasyncxhr openメソッドのパラメーターに適用されます)。
フレデリック

42

と関数を使用して$.ajaxいませんが、応答を待つ必要がある場合は、これを使用します。$.post$.get

$.ajaxSetup({async: false});
$.get("...");

34

基になるXMLHttpRequestオブジェクト(jQueryが要求を行うために使用)は、非同期プロパティをサポートしています。falseに設定します。お気に入り

async: false

24

通常は設計が悪いasyncをfalseに設定する代わりに、操作が保留されている間はUIをブロックすることを検討してください。

これは、jQueryのpromiseで次のようにうまく実現できます。

// same as $.ajax but settings can have a maskUI property
// if settings.maskUI==true, the UI will be blocked while ajax in progress
// if settings.maskUI is other than true, it's value will be used as the color value while bloking (i.e settings.maskUI='rgba(176,176,176,0.7)'
// in addition an hourglass is displayed while ajax in progress
function ajaxMaskUI(settings) {
    function maskPageOn(color) { // color can be ie. 'rgba(176,176,176,0.7)' or 'transparent'
        var div = $('#maskPageDiv');
        if (div.length === 0) {
            $(document.body).append('<div id="maskPageDiv" style="position:fixed;width:100%;height:100%;left:0;top:0;display:none"></div>'); // create it
            div = $('#maskPageDiv');
        }
        if (div.length !== 0) {
            div[0].style.zIndex = 2147483647;
            div[0].style.backgroundColor=color;
            div[0].style.display = 'inline';
        }
    }
    function maskPageOff() {
        var div = $('#maskPageDiv');
        if (div.length !== 0) {
            div[0].style.display = 'none';
            div[0].style.zIndex = 'auto';
        }
    }
    function hourglassOn() {
        if ($('style:contains("html.hourGlass")').length < 1) $('<style>').text('html.hourGlass, html.hourGlass * { cursor: wait !important; }').appendTo('head');
        $('html').addClass('hourGlass');
    }
    function hourglassOff() {
        $('html').removeClass('hourGlass');
    }

    if (settings.maskUI===true) settings.maskUI='transparent';

    if (!!settings.maskUI) {
        maskPageOn(settings.maskUI);
        hourglassOn();
    }

    var dfd = new $.Deferred();
    $.ajax(settings)
        .fail(function(jqXHR, textStatus, errorThrown) {
            if (!!settings.maskUI) {
                maskPageOff();
                hourglassOff();
            }
            dfd.reject(jqXHR, textStatus, errorThrown);
        }).done(function(data, textStatus, jqXHR) {
            if (!!settings.maskUI) {
                maskPageOff();
                hourglassOff();
            }
            dfd.resolve(data, textStatus, jqXHR);
        });

    return dfd.promise();
}

これであなたは今やることができます:

ajaxMaskUI({
    url: url,
    maskUI: true // or try for example 'rgba(176,176,176,0.7)'
}).fail(function (jqXHR, textStatus, errorThrown) {
    console.log('error ' + textStatus);
}).done(function (data, textStatus, jqXHR) {
    console.log('success ' + JSON.stringify(data));
});

そして、UIはajaxコマンドが戻るまでブロックします

jsfiddleを参照


asyncをfalseに設定しても、1行のコードを除いてまったく同じことをしませんか?
ヴィンセント

4
どういたしまして。asyncをfalseに設定すると、リクエストが非同期になります。つまり、通常は悪い習慣です。たとえば、イベント、他のajaxリクエスト、タイムアウトなどは処理されません。上記のコードを変更して、ajaxの処理中にUIの一部のみをブロックすることもできます(つまり、影響を受ける部分)
kofifus

11

or successを返す代わりに、適切なページをロードするように関数をコーディングすると、状況が簡単になると思います。truefalse

たとえば、返す代わりに次のようにtrueすることができます:

window.location="appropriate page";

このように、success関数が呼び出されると、ページがリダイレクトされます。


5

最近のJS では、次のようにasync/を使用するだけですawait

  async function upload() {
    return new Promise((resolve, reject) => {
        $.ajax({
            url: $(this).attr('href'),
            type: 'GET',
            timeout: 30000,
            success: (response) => {
                resolve(response);
            },
            error: (response) => {
                reject(response);
            }
        })
    })
}

次に、次のasyncような関数で呼び出します。

let response = await upload();

1
あなたのコードは機能しません...あなたは正しい軌道に乗っていますが、現状では機能しません。
ppetree

もう少し詳しく説明してもらえますか?私がこの質問に答えたコードをテストした後、それはうまくいくはずです。
タオヒドゥルイスラム教

awaitは、非同期関数の外では使用できません。エラーがスローされます。
ppetree

はい、私はそれを私の回答の最後の2行目、「それからasync関数で呼び出す」で述べました。
タオヒドゥルイスラム教

これは素晴らしい解決策ですが、素晴らしい解決策を探している他の人を支援するには(私がそうであったように)、コードを編集して、より完全な方法でそれを表示する必要があります。おそらく、フィドルへのリンクも含まれます。それは素晴らしいでしょう!
ppetree

0

ここで言及されていないので、jQuery whenステートメントがこの目的に非常に役立つ可能性があることも指摘したいと思いました。

彼らの例は次のようになります:

$.when( $.ajax( "test.aspx" ) ).then(function( data, textStatus, jqXHR ) {
  alert( jqXHR.status ); // Alerts 200
});

「then」部分は、「when」部分が終了するまで実行されません。


0

要求が完了するまで待機する必要があります。その後、関数が呼び出された場所からgetリクエストの本文を返します。

function foo() {
    var jqXHR = $.ajax({
        url: url,
        type: 'GET',
        async: false,
    });
    return JSON.parse(jqXHR.responseText);  
}

解決策を説明してください。
ドロップアウト

1
@Dropoutを追加しました。
Hassan Ejaz

@Hassan Ejaz、ありがとう!説明がなく、コードのみである回答には、労力が少ないというフラグが付けられます。
ドロップアウト
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.