이전 기능이 완료된 후 기능 호출


179

다음 JavaScript 코드가 있습니다.

$('a.button').click(function(){
    if (condition == 'true'){
        function1(someVariable);
        function2(someOtherVariable);
    }
    else {
        doThis(someVariable);
    }
});

완료된 function2후에 만 호출 되도록하려면 어떻게해야 function1합니까?


24
되고 function1비동기 동작을 수행?
LiraNuna

8
Yads, function1에 애니메이션이 포함되어 있으면 function1의 애니메이션이 계속 발생하는 동안 function2가 실행됩니다. function1에서 시작한 모든 것이 완전히 완료 될 때까지 function2를 어떻게 기다리게 하시겠습니까?
trusktr

누군가 function1이 완료 될 때까지 function2가 호출되지 않도록하기 위해 수행해야하는 이유가 무엇인지 설명해 줄 수 있습니까? 여기서 비동기 작업이 발생하지 않으므로이 작업이 동기식이므로 function1이 완료 될 때까지 function2가 실행되지 않습니다.
Aaron

답변:


206

익명 콜백을 지정하고 function1이이를 수락하도록하십시오.

$('a.button').click(function(){
    if (condition == 'true'){
        function1(someVariable, function() {
          function2(someOtherVariable);
        });
    }
    else {
        doThis(someVariable);
    }
});


function function1(param, callback) {
  ...do stuff
  callback();
} 

11
+1이지만 1.5를 사용한다면 새로운 Deferreds 패턴을 사용할 수 있습니다
philwinkle

빠른 답변 감사합니다. 예, function1은 단순한 비동기 작업을 수행하고 있으므로 콜백을 작성해야한다고 생각하거나 philwinkle이 언급 한 지연된 비즈니스를 살펴보십시오. 다시 한 번 감사드립니다. 잠을 좀 자고 아침에 다시 해결해 보겠습니다.
Rrryyyaaannn

13
이 답변은 해결책이 아닙니다. 작동하지 않는 증거는 다음과 같습니다. jsfiddle.net/trusktr/M2h6e
trusktr

12
@MikeRobinson 문제는 다음과 같습니다. ...do stuff비동기식을 포함하는 경우 어떻게해야 합니까? Function2는 여전히 예상 할 때 발생하지 않습니다. 위의 의견에있는 예제는 foo()함수에 비동기 코드가 있기 때문에 bar()내용을 foo()실행 한 후에도 내용을 실행 하지 않으며 , 차례로 $.when().then()호출 하는데도 사용 하지 않습니다 . 이 답변은 ...do stuff코드의 모든 내용 이 엄격하게 동기화 된 경우에만 유효합니다 .
trusktr

1
@trusktr이 경우 첫 번째 콜백을 n 번째 수준의 비동기 호출 로 계속 전달한 다음 callBack()모든 n 개의 비동기 호출이 완료된 후 시작해야 합니다. OP는 함수에서 수행중인 작업을 언급하지 않았으므로 한 수준의 비동기 호출로 가정했습니다.
GoodSp33d 4

96

jQuery 1.5를 사용하는 경우 새로운 Deferreds 패턴을 사용할 수 있습니다.

$('a.button').click(function(){
    if(condition == 'true'){
        $.when(function1()).then(function2());
    }
    else {
        doThis(someVariable);
    }
});

편집 : 업데이트 된 블로그 링크 :

Rebecca Murphy는 여기에 큰 글씨를 썼습니다 : http://rmurphey.com/blog/2010/12/25/deferreds-coming-to-jquery/


2
그러나 이것이 실례입니까? 연기되는 것은 무엇입니까? function1과 function2를 즉시 실행하고 있습니다. (저는 최초의 주석가가 아닙니다.)
user113716

10
그것은 나를 위해 전혀 효과가 없습니다. function1과 function2는 모두 정확히 동시에 (사람의 눈으로 볼 수있는) 실행됩니다. 여기에 작은 예가 있습니다 : jsfiddle.net/trusktr/M2h6e
trusktr

1
Rebecca Murphy의 글은 Defferds가 jQuery에 소개되기 전에 작성되었으며 작성자가이를 어떻게 구현할 것이라고 생각하는지에 따라 예제를 사용합니다. 이 기능을 실제로 사용하는 방법을 보려면 jQuery의 사이트를 방문하십시오 : api.jquery.com/jQuery.Deferred
Spencer Williams

1
jQuery 1.5 또는 최신 버전을 사용하더라도 $.when(function1).then(function2);(함수를 호출하는 괄호없이) 원하지 않습니까?
Teepeemm

1
몇 년 늦게이 의견을 읽습니다. function1약속을 돌려줘야합니다. 이 경우 참조가 아닌 실제 실행 된 함수 여야합니다. resolve그 약속이 부름을 받으면 그때 function2실행됩니다. 이것은 function1아약스 호출이 있다고 가정하여 쉽게 설명 할 수 있습니다 . done콜백는 약속을 해결하는 것입니다. 나는 그것이 분명하기를 바랍니다.
philwinkle

46

이 시도 :

function method1(){
   // some code

}

function method2(){
   // some code
}

$.ajax({
   url:method1(),
   success:function(){
   method2();
}
})

37

이 답변은 표준 promises의 JavaScript 기능인을 사용합니다 ECMAScript 6. 대상 플랫폼이 지원하지 않으면 promisesPromiseJs로 폴리 필하십시오 .

약속은 JavaScript에서 비동기 작업을 처리하는 새롭고 훨씬 나은 방법입니다.

$('a.button').click(function(){
    if (condition == 'true'){
        function1(someVariable).then(function() {
            //this function is executed after function1
            function2(someOtherVariable);
        });
    }
    else {
        doThis(someVariable);
    }
});


function function1(param, callback) {
    return new Promise(function (fulfill, reject){
        //do stuff
        fulfill(result); //if the action succeeded
        reject(error); //if the action did not succeed
    });
} 

이 간단한 예제에서는 상당한 오버 헤드처럼 보일 수 있지만 복잡한 코드의 경우 콜백을 사용하는 것보다 훨씬 낫습니다. 여러 then명령문을 사용하여 여러 비동기 호출을 쉽게 연결할 수 있습니다 .

function1(someVariable).then(function() {
    function2(someOtherVariable);
}).then(function() {
    function3();
});

또한 jQuery 지연을 쉽게 랩핑하여 $.ajax호출 에서 리턴 할 수 있습니다 .

Promise.resolve($.ajax(...params...)).then(function(result) {
    //whatever you want to do after the request
});

@charlietfl이 지적했듯이,에 jqXHR의해 반환 된 객체 $.ajax()Promise인터페이스 를 구현합니다 . 실제로 실제로 랩핑 할 필요는 없으며 Promise직접 사용할 수 있습니다.

$.ajax(...params...).then(function(result) {
    //whatever you want to do after the request
});

Promise.resolve랩핑 $.ajax$.ajax반가운 약속 이후 반 패턴입니다
charlietfl

@charlietfl 그러나 실제는 아니며 Promise인터페이스 만 구현합니다. 실제 Promisethen메소드에 전달할 때 어떻게 작동하는지 , Promise.alla jqXHR와 a Promise가 전달 되면 어떻게 할 것인지 잘 모르겠습니다 . 이를 위해서는 추가 테스트가 필요합니다. 그러나 힌트를 주셔서 감사합니다. 대답에 추가하겠습니다!
Domysee

실제로 jQuery 버전 3+에서는 Promises A +를 준수합니다. 선명하게 촬상는 $.ajax.then새로운 것이 아니다
charlietfl

21

또는 하나의 함수가 완료되면 사용자 지정 이벤트를 트리거 한 다음 문서에 바인딩 할 수 있습니다.

function a() {
    // first function code here
    $(document).trigger('function_a_complete');
}

function b() {
    // second function code here
}

$(document).bind('function_a_complete', b);

이 방법을 사용하면 기능 a는 실행이 완료된 경우에만 트리거가 존재하므로 기능 'b'는 AFTER 기능 'a'만 실행할 수 있습니다.


"jQuery 1.7부터 .on () 메소드는 문서에 이벤트 핸들러를 첨부하는 데 선호되는 메소드입니다." api.jquery.com/bind
CodeVirtuoso


3

이것은 function1이 수행하는 작업에 따라 다릅니다.

function1이 div 값이나 다른 것을 업데이트하는 것과 같은 간단한 동기화 자바 스크립트를 수행하는 경우 function1이 완료된 후 function2가 시작됩니다.

function1이 AJAX 호출과 같은 비동기 호출을 수행하는 경우 "콜백"메소드를 작성해야합니다 (대부분의 ajax API에는 콜백 함수 매개 변수가 있음). 그런 다음 콜백에서 function2를 호출하십시오. 예 :

function1()
{
  new AjaxCall(ajaxOptions, MyCallback);
}

function MyCallback(result)
{
  function2(result);
}

2

방법 1, 방법 2, 3, 4 이후에 방법 1을 실행해야하는 경우 다음 코드 스 니펫은 JavaScript의 Deferred 오브젝트를 사용하여이를위한 솔루션이 될 수 있습니다.

function method1(){
  var dfd = new $.Deferred();
     setTimeout(function(){
     console.log("Inside Method - 1"); 
     method2(dfd);	 
    }, 5000);
  return dfd.promise();
}

function method2(dfd){
  setTimeout(function(){
   console.log("Inside Method - 2"); 
   method3(dfd);	
  }, 3000);
}

function method3(dfd){
  setTimeout(function(){
   console.log("Inside Method - 3"); 	
   dfd.resolve();
  }, 3000);
}

function method4(){   
   console.log("Inside Method - 4"); 	
}

var call = method1();

$.when(call).then(function(cb){
  method4();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


0

function1이 완료하는 데 시간이 걸리기 때문에 비동기로 바꾸려는 동기화 함수이고 콜백을 추가하도록 제어 할 수없는 경우 :

function function1 (someVariable) {
    var date = Date.now ();
    while (Date.now () - date < 2000);      // function1 takes some time to complete
    console.log (someVariable);
}
function function2 (someVariable) {
    console.log (someVariable);
}
function onClick () {
    window.setTimeout (() => { function1 ("This is function1"); }, 0);
    window.setTimeout (() => { function2 ("This is function2"); }, 0);
    console.log ("Click handled");  // To show that the function will return before both functions are executed
}
onClick ();

출력은 다음과 같습니다.

Click handled

... 2 초 후 :

This is function 1
This is function 2

window.setTimeout ()을 호출하면 비동기 실행 호출이 수행하는 JS 실행 작업 루프에 작업이 추가되고 JS 런타임의 "실행 완료"의 기본 원칙이 onClick ()을 보장하기 때문에 작동합니다. 끝나기 전에 중단되지 않습니다.

코드를 이해하기 어려울 수있는 것만 큼 재미 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.