jQuery가 Ajax 호출이 종료되기 전에 대기하도록하려면 어떻게해야합니까?


244

로그인이 필요한 서버 측 기능이 있습니다. 사용자가 로그인 한 경우이 기능은 성공시 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가 async를 false로 설정하는 것은 나쁜 디자인이며 "시간 초과 등은 처리되지 않습니다"라고 지적한 것처럼 오래된 스레드 일 수 있습니다. 이 간단한 솔루션을 사용해보십시오.- stackoverflow.com
Shan

답변:


357

$.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의 요점과 반대되는 점에 주목할 것입니다. 또한 errorsuccess함수 에서 응답을 처리해야합니다 . 이러한 함수는 서버에서 응답을 수신 한 경우에만 호출됩니다.


10
내 의견으로는 좋은 관행을 따르는 것이 판단되지 않으며 StackOverflow에서 가장 좋은 답변 중 일부입니다.
Semperos

68
사용하지 마십시오 async: false. 신뢰할 수없는 네트워크 I / O를 기다리는 동안 브라우저의 이벤트 루프가 정지됩니다. 항상 더 좋은 방법이 있습니다. 이 경우 링크의 대상은 사용자 세션과 302를 로그인 페이지로 확인할 수 있습니다.
Matthew

3
테스트 async: false를 위해 매우 유용 할 수 있습니다.
Jarrett

4
@Matthew 정말? 다른 페이지로 사용자를 보내거나 새로 고치기 전에 비동기로 ajax를 보내는 대안은 무엇입니까?
NoBugs

2
asyncfalse대부분의 브라우저 사용 사례에서는 값 이 더 이상 사용되지 않습니다. 최신 버전의 브라우저에서는 예외가 발생할 수 있습니다. xhr.spec.whatwg.org/#sync-warning(jQuery를 사용하는 asyncxhr open메소드의 매개 변수에 적용됨)을 참조하십시오 .
Frédéric

42

내가 사용하고 있지 않다 $.ajax$.post하고 $.get내가 응답을 기다릴 필요가 그렇다면, 기능을, 내가 이것을 사용 :

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

34

기본 XMLHttpRequest 객체 (요청을 위해 jQuery에서 사용)는 비동기 속성을 지원합니다. false로 설정하십시오 . 처럼

async: false

24

일반적으로 잘못된 디자인 인 async를 false로 설정하는 대신 작업이 보류중인 동안 UI를 차단하는 것이 좋습니다.

이것은 다음과 같이 jQuery 약속으로 훌륭하게 달성 할 수 있습니다.

// 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));
});

그리고 ajax 명령이 반환 될 때까지 UI가 차단됩니다.

jsfiddle 참조


async를 false로 설정하지 않으면 한 줄의 코드를 제외하고 똑같은 일을합니까?
Vincent

4
전혀. async를 false로 설정하면 요청이 비 동기화됩니다. 즉, 이벤트, 다른 아약스 요청, 시간 초과 등과 같은 일반적으로 나쁜 습관이 될 때까지 처리가 중단됩니다. 아약스가 처리되는 동안 UI의 일부만 차단하도록 위의 코드를 수정할 수도 있습니다 (예 : 영향을받는 부분)
kofifus

11

나는 일을 당신이 당신의 코드를하면 쉬울 것이라고 생각 success반환하는 대신 해당 페이지를로드하는 기능을 true하거나 false.

예를 들어 돌아 오는 대신 true다음을 수행 할 수 있습니다.

window.location="appropriate page";

그렇게하면 성공 함수가 호출 될 때 페이지가 리디렉션됩니다.


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

좀 더 자세히 설명해 주시겠습니까? 이 질문에 답한 코드를 테스트 한 후에 작동합니다.
Taohidul 이슬람

await는 비동기 함수 외부에서 사용할 수 없으며 오류가 발생합니다.
ppetree

예, 나는 대답의 두 번째 마지막 줄에서 "그런 다음 async함수로 호출하십시오"라고 언급했습니다 .
Taohidul 이슬람

훌륭한 솔루션이지만 (나처럼) 훌륭한 솔루션을 찾는 다른 사람들을 돕기 위해 코드를 편집하여보다 완전한 방식으로 표시해야합니다. 아마도 바이올린에 대한 링크를 포함 할 수도 있습니다. 대단 할 것입니다!
ppetree

0

여기에 언급되어 있지 않으므로 jQuery when 문 이이 목적에 매우 유용 할 수 있다고 생각했습니다.

그들의 예는 다음과 같습니다 :

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

"다음"부분은 "언제"부분이 완료 될 때까지 실행되지 않습니다.


0

요청이 완료 될 때까지 기다려야합니다. 그런 다음 함수가 호출 된 곳에서 요청 본문을 반환합니다.

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

솔루션을 설명하십시오.
드롭 아웃

1
@ 드롭 아웃을 추가했습니다.
Hassan Ejaz

감사합니다 @Hassan Ejaz! 설명이없고 코드 만있는 답변은 낮은 노력으로 표시됩니다.
드롭 아웃
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.