2010-04-14 4 views
17

좋아요, 자바 스크립트가 C#이나 PHP가 아니지만 Javascript의 문제로 되돌아 가도록 고맙게 생각합니다. JS 자체가 아닌 내 용도로 사용하겠습니다.어떻게하면 자바 스크립트 코드를 * 순서대로 실행합니까 *

내가하는 기능을 가지고 다음 'hideLoader'기능이 바로 후 실행되기 때문에

function updateStatuses(){ 

showLoader() //show the 'loader.gif' in the UI 

updateStatus('cron1'); //performs an ajax request to get the status of something 
updateStatus('cron2'); 
updateStatus('cron3'); 
updateStatus('cronEmail'); 
updateStatus('cronHourly'); 
updateStatus('cronDaily'); 

hideLoader(); //hide the 'loader.gif' in the UI 

} 

점은 코드에서 앞서 뛰어 자바 스크립트의 불타는 욕망 때문에,이다, 로더는 결코 나타나지 않습니다.

어떻게 해결할 수 있습니까? 또는 다른 말로하면 어떻게 JavaScript 함수를 페이지에 쓰는 순서대로 실행시킬 수 있습니까?

+0

Promise는 모든 비동기 요청을 처리하는 데 가장 적합한 개체입니다. [Promise 객체로 비동기 요청 수정] (https://stackoverflow.com/a/47719849/7487135) –

답변

14

AJAX는 본질적으로 비동기이기 때문에 문제가 발생합니다. 즉, updateStatus() 호출은 실제로 순서대로 실행되지만 immediatly를 반환하고 JS 인터프리터는 AJAX 요청에서 데이터가 검색되기 전에 hideLoader()에 도달합니다.

AJAX 호출이 완료된 경우 hideLoader()을 수행해야합니다.

+0

JS는 updateStatus 작업이 완료 될 때까지 기다리지 않고 다음 작업을 시작합니다. cron2가 시작되기 전에 cron1을 완료해야하는 경우 이전 update의 성공시 실행되도록 각 updateStatus를 설정해야합니다. – MindStalker

2

이 코드의 실행 순서와는 아무런 관련이 없습니다.

로더 이미지가 표시되지 않는 이유는 함수가 실행되는 동안 UI가 업데이트되지 않기 때문입니다. UI에서 변경을 수행하면 함수를 종료하고 브라우저에 제어를 반환 할 때까지 변경 사항이 표시되지 않습니다.

당신은 코드의 나머지를 시작하기 전에 UI를 업데이트하는 브라우저에게 기회를주는 이미지를 설정 한 후 제한 시간을 사용할 수 있습니다

function updateStatuses(){ 

    showLoader() //show the 'loader.gif' in the UI 

    // start a timeout that will start the rest of the code after the UI updates 
    window.setTimeout(function(){ 
    updateStatus('cron1'); //performs an ajax request to get the status of something 
    updateStatus('cron2'); 
    updateStatus('cron3'); 
    updateStatus('cronEmail'); 
    updateStatus('cronHourly'); 
    updateStatus('cronDaily'); 

    hideLoader(); //hide the 'loader.gif' in the UI 
    },0); 
} 

은 또한 당신의 코드를 만들 수있는 또 다른 요인이 실행 나타납니다 고장난. AJAX 요청이 비동기 인 경우 함수는 응답을 기다리지 않습니다. 브라우저가 응답을 받으면 응답을 처리하는 함수가 실행됩니다. 응답을 수신 한 후 로더 이미지를 숨기려면 마지막 응답 핸들러 기능이 실행될 때 수행해야합니다. 응답을 요청한 순서대로 응답 할 필요가 없으므로 마지막 응답이 오면 얼마나 많은 응답을 알 수 있는지 계산해야합니다.

+0

Guffa와 Dr. Sbaitso 덕분에 후드 아래에서 무슨 일이 벌어지고 있는지 더 많이 알게되었습니다. 나는 당신의 제안을 시도하고 내가 할 수있는 것을 보게 될 것입니다! –

1

방화범은 다음 showLoader, updateStatus 및 hideLoader 각각 다음과 같은 라인을 추가 설치 : 당신은 콘솔 창에 함수에 대한 호출을 나열 볼 수 있습니다, 그들은 순서에있을 것입니다

Console.log("event logged"); 

. 질문, 귀하의 "updateStatus"방법은 무엇입니까?

아마도 백그라운드 작업을 시작한 다음 반환되므로 백그라운드 작업이 완료되기 전에 hideLoader가 호출됩니다. Ajax 라이브러리에는 "OnComplete"또는 "OnFinished"콜백이있을 수 있습니다. 거기에서 다음 updateStatus를 호출하십시오.

+0

updateStatus 메서드는 jquery ajax 호출을 시작합니다. 'Onsuccess'콜백에서 로더를 숨길 수없는 이유는 여러 호출이 완료 될 때까지 기다려야하기 때문입니다. 하지만 아래의 '카운터'접근법을 사용하면 해결 방법이 있습니다. –

12

AJAX 프로그래밍을하는 경우 JavaScript를 절차 기반이 아닌 이벤트 기반으로 생각해야합니다. 첫 번째 호출이 완료 될 때까지 기다렸다가 두 번째 호출을 실행해야합니다. 이를 수행하는 방법은 두 번째 호출을 첫 번째 호출이 끝날 때 발생하는 콜백에 바인딩하는 것입니다.(잘하면 당신이 라이브러리를 사용하는) 당신의 AJAX 라이브러리의 내부 동작에 대한 자세한 내용을 모른 채 나는 어떻게이 작업을 수행하는 방법을 말할 수 있지만, 그것은 아마도 같은 것을 볼 것이다 :

showLoader(); 

    updateStatus('cron1', function() { 
    updateStatus('cron2', function() { 
     updateStatus('cron3', function() { 
     updateStatus('cronEmail', function() { 
      updateStatus('cronHourly', function() { 
      updateStatus('cronDaily', funciton() { hideLoader(); }) 
      }) 
     }) 
     }) 
    }) 
    }) 
}); 

아이디어입니다 updateStatus은 일반적인 인수와 함께 완료 될 때 실행할 콜백 함수를 사용합니다. 그러한 훅을 제공하는 함수에 onComplete을 실행하는 함수를 전달하는 것은 합리적으로 일반적인 패턴입니다. 당신이 jQuery를 사용하는 경우

업데이트

, 당신은 $.ajax() 여기에 읽을 수 있습니다 http://api.jquery.com/jQuery.ajax/

귀하의 코드는 아마이 같은 같습니다

function updateStatus(arg) { 
    // processing 

    $.ajax({ 
    data : /* something */, 
    url : /* something */ 
    }); 

    // processing 
} 

당신은 수정할 수 있습니다 당신의 다음과 같이 두 번째 매개 변수로 콜백 함수를 사용하는 함수 :

01 2,

}

+0

안녕하세요 Meagar, jquery를 사용하고 있습니다. 구현 방법은 무엇입니까? –

5

우리는 우리의 프로젝트 중 하나에서 비슷한을 가지고, 우리는 카운터를 사용하여 그것을 해결. 각 호출마다 카운터를 늘려 AJAX 요청의 응답 함수에서 사용하는 경우 (사용중인 AJAX JavaScript 라이브러리에 따라 다름)

카운터가 0이되면 모든 AJAX 요청이 완료되고 hideLoader()으로 전화하십시오. updateStatus 다른 함수 호출

var loadCounter = 0; 

function updateStatuses(){ 
    updateStatus('cron1'); //performs an ajax request to get the status of something 
    updateStatus('cron2'); 
    updateStatus('cron3');  
    updateStatus('cronEmail'); 
    updateStatus('cronHourly'); 
    updateStatus('cronDaily'); 
} 

function updateStatus(what) { 
    loadCounter++; 

    //perform your AJAX call and set the response method to updateStatusCompleted() 
} 

function updateStatusCompleted() { 
    loadCounter--; 
    if (loadCounter <= 0) 
     hideLoader(); //hide the 'loader.gif' in the UI 
} 
+0

안녕하세요 Prutswonder, 방금 시도하고 작동합니다! 나는 솔루션을 좋아한다 –

+3

에드, 당신이이 솔루션들 중 하나를 원한다면 그 사람의 대답 옆에있는 체크 박스를 클릭하여 당신이 선택한 최상의 솔루션을 표시 할 수 있었습니까? –

+0

+1 콜백의 중첩 된 시리즈에 대한 내 솔루션보다 더 나은 것 – meagar

0

이동 :

다음은 샘플입니다. 새 함수를 대상으로 setTimeout을 호출합니다.

만약 당신의 ajax 요청이 비동기 적이라면 어떤 것을 완료했는지 추적 할 것이 있습니다. 각 콜백 메소드는 "완성 된"플래그를 어딘가에 설정할 수 있으며 마지막으로 수행 할 것인지를 확인합니다. 그렇다면 hideLoader를 호출하게합니다.

1

다른 사람들도 지적했듯이 동기 작업을 원하지 않습니다. Async를 포용하면 AJAX의 A가 의미하는 것입니다.

나는 sync v/s 비동기에 대한 훌륭한 비유에 대해서 언급하고자한다. entire post on the GWT forum을 읽을 수 있습니다. 관련성있는 비유만을 포함하고 있습니다. 당신이 경우 상상

은 ...

당신은 TV를보고 소파에 앉아, 당신은 맥주 밖에있는 것을 알고있다, 당신은 주류 판매점까지 실행을 기쁘게 당신의 배우자에게 그리고 일부를 가져옵니다. 귀하의 배우자가 앞문을 나서 자마자 당신은 번을 냉장고에 놓고 소파에서 일어나 트렁크를 엽니 다. 놀랍게도 맥주는 입니다.

물론 맥주가 없으므로 배우자는 주류 판매점 에 여전히 있습니다. 에 맥주가 있으니 전에 그가 돌아 오는 동안 [s]까지 기다려야합니다.

하지만 동기를 원하십니까? 당신의 주위에 전 세계가 정지 , 당신은 숨을하지 마십시오 문 답하거나 끝까지 볼

은 ... 배우자가, 지금 ... 문 밖으로 걸어 ... 다시 상상하여 쇼 [그가] 에 마을을 가로 질러 실행하는 동안 맥주를 가져옵니다. 당신은 나중에 구급차 및 배우자에 둘러싸여 일부 한정없는 때 나는 가 맥주를 가지고, 야, 오 말을 깨어 난 ...이 앉아 당신이 의식을 잃을 때까지하지 파란색 회전 근육을 이동하고, 에 도착.

동기식 서버 호출을 주장 할 때 발생합니다. 그래서 Ajax 호출은 다음과 같을 것이다

async: false, 

을 :

10

당신이해야 할 생각은 코드에서 이것을 가지고있다

jQuery.ajax({ 
      type: "GET", 
      url: "something.html for example", 
      dataType: "html", 
      async: false, 
      context: document.body, 
      success: function(response){ 

       //do stuff here 

      }, 
      error: function() { 
       alert("Sorry, The requested property could not be found."); 
      } 
     }); 
분명히

XML에 대한 변경이 필요 일부 , JSON 등이 있지만 여기서는 async: false,이 JS 엔진에게 성공 호출이 반환 될 때까지 기다린 다음 (계속 실패 할 때까지) 대기하고 계속 수행 할 것을 지시하는 주요 지점입니다. 거기에는 단점이 있으며, 아약스가 돌아 오기 전까지는 전체 페이지가 응답하지 않는다는 것을 기억하십시오 !!! 일반적으로 밀리 세컨드 이내에 큰 거래는 아니지만 더 오래 걸릴 수 있습니다.

희망이 정답이고 그것을 당신 : 모든 비동기 요청을 처리하기위한 최상의 솔루션의

+0

이것은 하나의 트릭을했다. 간단하고 간결한 솔루션. 고마워. – darksoulsong

+0

그것이 효과가있는 동안 이것은 굉장한 대답이 아니다. JS가 비동기가되기를 원한다. 당신이 그것을 가고 싶어하는 많은 장점과 시나리오가 있습니다. 그것은 당신 자신의 일이고, 당신의 전체 앱을위한 모든 것을 끄는 것이 드문 것입니다. 대신 약속 라이브러리를 사용하는 것이 좋습니다. 다음은 훌륭한 자습서입니다. http://dailyjs.com/2014/02/20/promises-in-detail/ – Codex

0

하나는 '약속'가 있습니다.
Promise 개체는 비동기 작업의 최종 완료 (또는 실패)를 나타냅니다.

예 :

let myFirstPromise = new Promise((resolve, reject) => { 
    // We call resolve(...) when what we were doing asynchronously was successful, and reject(...) when it failed. 
    // In this example, we use setTimeout(...) to simulate async code. 
    // In reality, you will probably be using something like XHR or an HTML5 API. 
    setTimeout(function(){ 
    resolve("Success!"); // Yay! Everything went well! 
    }, 250); 
}); 

myFirstPromise.then((successMessage) => { 
    // successMessage is whatever we passed in the resolve(...) function above. 
    // It doesn't have to be a string, but if it is only a succeed message, it probably will be. 
    console.log("Yay! " + successMessage); 
}); 

Promise

다음과 같이 3 개 비동기 기능을 가지고 있으며, 순서대로 실행 할 것으로 예상 할 경우이 방법을

let FirstPromise = new Promise((resolve, reject) => { 
    FirstPromise.resolve("First!"); 
}); 
let SecondPromise = new Promise((resolve, reject) => { 

}); 
let ThirdPromise = new Promise((resolve, reject) => { 

}); 
FirstPromise.then((successMessage) => { 
    jQuery.ajax({ 
    type: "type", 
    url: "url", 
    success: function(response){ 
     console.log("First! "); 
     SecondPromise.resolve("Second!"); 
    }, 
    error: function() { 
     //handle your error 
    } 
    });   
}); 
SecondPromise.then((successMessage) => { 
    jQuery.ajax({ 
    type: "type", 
    url: "url", 
    success: function(response){ 
     console.log("Second! "); 
     ThirdPromise.resolve("Third!"); 
    }, 
    error: function() { 
     //handle your error 
    } 
    });  
}); 
ThirdPromise.then((successMessage) => { 
    jQuery.ajax({ 
    type: "type", 
    url: "url", 
    success: function(response){ 
     console.log("Third! "); 
    }, 
    error: function() { 
     //handle your error 
    } 
    }); 
}); 

, 원하는대로 모든 비동기 조작을 처리 할 수 ​​있습니다.

관련 문제