IT박스

함수를 하나씩 실행하기 위해 3 개의 함수를 어떻게 호출해야합니까?

itboxs 2020. 6. 27. 11:49
반응형

함수를 하나씩 실행하기 위해 3 개의 함수를 어떻게 호출해야합니까?


이 함수를 하나씩 호출해야하는 경우

$('#art1').animate({'width':'1000px'},1000);        
$('#art2').animate({'width':'1000px'},1000);        
$('#art3').animate({'width':'1000px'},1000);        

jQuery에서 다음과 같은 작업을 수행 할 수 있다는 것을 알고 있습니다.

$('#art1').animate({'width':'1000px'},1000,'linear',function(){
    $('#art2').animate({'width':'1000px'},1000,'linear',function(){
        $('#art3').animate({'width':'1000px'},1000);        
    });        
});        

그러나 jQuery를 사용하지 않고 전화를 걸고 싶다고 가정 해 봅시다.

some_3secs_function(some_value);        
some_5secs_function(some_value);        
some_8secs_function(some_value);        

실행하기 위해이 함수를 호출하고 호출이 some_3secs_function끝난 후 실행 한 다음 some_5secs_function호출이 종료 된 후 호출하는 방법은 some_8secs_function무엇입니까?

최신 정보:

여전히 작동하지 않습니다.

(function(callback){
    $('#art1').animate({'width':'1000px'},1000);
    callback();
})((function(callback2){
    $('#art2').animate({'width':'1000px'},1000);
    callback2();
})(function(){
    $('#art3').animate({'width':'1000px'},1000);
}));

세 애니메이션이 동시에 시작됩니다

내 실수는 어디에?


자바 스크립트에는 동기식비동기식 기능이 있습니다.

동기 함수

Javascript의 대부분의 함수는 동기식입니다. 여러 개의 동기 함수를 연속으로 호출하려는 경우

doSomething();
doSomethingElse();
doSomethingUsefulThisTime();

그들은 순서대로 실행됩니다. 완료 doSomethingElse될 때까지 시작되지 않습니다 doSomething. doSomethingUsefulThisTime, doSomethingElse완료 될 때까지 시작되지 않습니다 .

비동기 함수

그러나 비동기 기능은 서로를 기다리지 않습니다. 함수가 비동기 적이라고 가정하고, 위와 같은 코드 샘플을 보자.

doSomething();
doSomethingElse();
doSomethingUsefulThisTime();

기능은 순서대로 초기화되지만 모두 동시에 실행됩니다. 어느 쪽이 먼저 끝날지 일관되게 예측할 수 없습니다. 실행하는 데 가장 짧은 시간이 걸리는 쪽이 먼저 끝납니다.

그러나 때때로 비동기식 함수가 순서대로 실행되기를 원하고 동기식 함수가 비동기식으로 실행되기를 원할 수도 있습니다. 다행히 콜백 및 타임 아웃이 각각 가능합니다.

콜백

하자 우리가 순서대로 실행하려는 것을 세 비동기 기능을 가지고 있다고 가정 some_3secs_function, some_5secs_function하고 some_8secs_function.

함수는 Javascript에서 인수로 전달 될 수 있으므로 함수가 완료된 후 실행할 콜백으로 함수를 전달할 수 있습니다.

우리가 이런 함수를 만들면

function some_3secs_function(value, callback){
  //do stuff
  callback();
}

다음과 같이 순서대로 호출 할 수 있습니다.

some_3secs_function(some_value, function() {
  some_5secs_function(other_value, function() {
    some_8secs_function(third_value, function() {
      //All three functions have completed, in order.
    });
  });
});

타임 아웃

Javascript에서는 특정 시간 초과 (밀리 초) 후에 함수가 실행되도록 지시 할 수 있습니다. 결과적으로 동기 함수가 비동기 적으로 동작하게 할 수 있습니다.

세 개의 동기 함수가있는 경우 함수를 사용하여 비동기 적으로 실행할 수 setTimeout있습니다.

setTimeout(doSomething, 10);
setTimeout(doSomethingElse, 10);
setTimeout(doSomethingUsefulThisTime, 10);

그러나 이것은 약간 추악하며 DRY 원칙 [wikipedia]을 위반합니다 . 함수 배열과 타임 아웃을 받아들이는 함수를 만들어서 약간 정리할 수 있습니다.

function executeAsynchronously(functions, timeout) {
  for(var i = 0; i < functions.length; i++) {
    setTimeout(functions[i], timeout);
  }
}

다음과 같이 호출 할 수 있습니다.

executeAsynchronously(
    [doSomething, doSomethingElse, doSomethingUsefulThisTime], 10);

요약하면, 비동기식으로 실행하려는 비동기 함수가있는 경우 콜백을 사용하고 비동기식으로 실행하려는 동기 함수가있는 경우 시간 종료를 사용하십시오.


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

내 대답은 여기를보십시오 . 애니메이션 을 사용하려면 다른 함수를 실행할 때까지 애니메이션이있는 함수가 끝날 때까지 기다리 십시오 jQuery.

다음은 코드의 모양이 ES6 PromisesjQuery animations입니다.

Promise.resolve($('#art1').animate({ 'width': '1000px' }, 1000).promise()).then(function(){
    return Promise.resolve($('#art2').animate({ 'width': '1000px' }, 1000).promise());
}).then(function(){
    return Promise.resolve($('#art3').animate({ 'width': '1000px' }, 1000).promise());
});

일반 메소드도 래핑 할 수 있습니다 Promises.

new Promise(function(fulfill, reject){
    //do something for 5 seconds
    fulfill(result);
}).then(function(result){
    return new Promise(function(fulfill, reject){
        //do something for 5 seconds
        fulfill(result);
    });
}).then(function(result){
    return new Promise(function(fulfill, reject){
        //do something for 8 seconds
        fulfill(result);
    });
}).then(function(result){
    //do something with the result
});

then방법은 곧만큼 실행 Promise완료. 일반적으로 function전달 된 대상 의 반환 값은 then결과로 다음 값으로 전달됩니다 .

그러나 a Promise가 반환되면 다음 then함수는 Promise실행 끝날 때까지 기다렸다가 그 결과 (에 전달되는 값 fulfill)를받습니다.


동기 함수 비동기 함수 실행 의 차이를 완전히 인식하지 못하는 것 같습니다 .

업데이트에서 제공 한 코드는 각 콜백 함수를 즉시 실행하여 애니메이션을 즉시 시작합니다. 그러나 애니메이션은 비동기 적으로 실행 됩니다. 다음과 같이 작동합니다.

  1. 애니메이션에서 단계 수행
  2. setTimeout다음 애니메이션 단계와 지연을 포함하는 함수로 호출
  3. 시간이 지남
  4. 주어진 콜백 setTimeout이 실행
  5. 1 단계로 돌아가십시오

이것은 애니메이션의 마지막 단계가 완료 될 때까지 계속됩니다. 그 동안 동기 기능이 오래 전에 완료되었습니다. 즉, animate함수 호출에 실제로 3 초가 걸리지 않습니다 . 지연 및 콜백으로 효과가 시뮬레이션됩니다.

필요한 것은 대기열 입니다. 내부적으로 jQuery는 애니메이션을 큐에 넣고 해당 애니메이션이 완료된 후에 만 콜백을 실행 합니다 . 콜백이 다른 애니메이션을 시작하면 효과가 순서대로 실행됩니다.

가장 간단한 경우 이것은 다음과 같습니다.

window.setTimeout(function() {
    alert("!");
    // set another timeout once the first completes
    window.setTimeout(function() {
        alert("!!");
    }, 1000);
}, 3000); // longer, but first

일반적인 비동기 루핑 기능은 다음과 같습니다. 주어진 함수를 순서대로 호출하고 각 함수 사이에 지정된 시간 (초) 동안 기다립니다.

function loop() {
    var args = arguments;
    if (args.length <= 0)
        return;
    (function chain(i) {
        if (i >= args.length || typeof args[i] !== 'function')
            return;
        window.setTimeout(function() {
            args[i]();
            chain(i + 1);
        }, 2000);
    })(0);
}    

용법:

loop(
  function() { alert("sam"); }, 
  function() { alert("sue"); });

구성 가능한 대기 시간이 걸리거나 즉시 첫 번째 기능을 실행 false하거나 체인 apply의 기능이 반환 되거나 지정된 컨텍스트의 기능 또는 기타 필요한 기능이 실행될 때 실행을 중지하도록 분명히 수정할 수 있습니다.


I believe the async library will provide you a very elegant way to do this. While promises and callbacks can get a little hard to juggle with, async can give neat patterns to streamline your thought process. To run functions in serial, you would need to put them in an async waterfall. In async lingo, every function is called a task that takes some arguments and a callback; which is the next function in the sequence. The basic structure would look something like:

async.waterfall([
  // A list of functions
  function(callback){
      // Function no. 1 in sequence
      callback(null, arg);
  },
  function(arg, callback){
      // Function no. 2 in sequence
      callback(null);
  }
],    
function(err, results){
   // Optional final callback will get results for all prior functions
});

I've just tried to briefly explain the structure here. Read through the waterfall guide for more information, it's pretty well written.


your functions should take a callback function, that gets called when it finishes.

function fone(callback){
...do something...
callback.apply(this,[]);

}

function ftwo(callback){
...do something...
callback.apply(this,[]);
}

then usage would be like:

fone(function(){
  ftwo(function(){
   ..ftwo done...
  })
});

asec=1000; 

setTimeout('some_3secs_function("somevalue")',asec*3);
setTimeout('some_5secs_function("somevalue")',asec*5);
setTimeout('some_8secs_function("somevalue")',asec*8);

I won't go into a deep discussion of setTimeout here, but:

  • in this case I've added the code to execute as a string. this is the simplest way to pass a var into your setTimeout-ed function, but purists will complain.
  • you can also pass a function name without quotes, but no variable can be passed.
  • your code does not wait for setTimeout to trigger.
  • This one can be hard to get your head around at first: because of the previous point, if you pass a variable from your calling function, that variable will not exist anymore by the time the timeout triggers - the calling function will have executed and it's vars gone.
  • I have been known to use anonymous functions to get around all this, but there could well be a better way,

Since you tagged it with javascript, I would go with a timer control since your function names are 3, 5, and 8 seconds. So start your timer, 3 seconds in, call the first, 5 seconds in call the second, 8 seconds in call the third, then when it's done, stop the timer.

Normally in Javascript what you have is correct for the functions are running one after another, but since it looks like you're trying to do timed animation, a timer would be your best bet.


//sample01
(function(_){_[0]()})([
	function(){$('#art1').animate({'width':'10px'},100,this[1].bind(this))},
	function(){$('#art2').animate({'width':'10px'},100,this[2].bind(this))},
	function(){$('#art3').animate({'width':'10px'},100)},
])

//sample02
(function(_){_.next=function(){_[++_.i].apply(_,arguments)},_[_.i=0]()})([
	function(){$('#art1').animate({'width':'10px'},100,this.next)},
	function(){$('#art2').animate({'width':'10px'},100,this.next)},
	function(){$('#art3').animate({'width':'10px'},100)},
]);

//sample03
(function(_){_.next=function(){return _[++_.i].bind(_)},_[_.i=0]()})([
	function(){$('#art1').animate({'width':'10px'},100,this.next())},
	function(){$('#art2').animate({'width':'10px'},100,this.next())},
	function(){$('#art3').animate({'width':'10px'},100)},
]);


You could also use promises in this way:

    some_3secs_function(this.some_value).then(function(){
       some_5secs_function(this.some_other_value).then(function(){
          some_8secs_function(this.some_other_other_value);
       });
    });

You would have to make some_value global in order to access it from inside the .then

Alternatively, from the outer function you could return the value the inner function would use, like so:

    one(some_value).then(function(return_of_one){
       two(return_of_one).then(function(return_of_two){
          three(return_of_two);
       });
    });

I use a 'waitUntil' function based on javascript's setTimeout

/*
    funcCond : function to call to check whether a condition is true
    readyAction : function to call when the condition was true
    checkInterval : interval to poll <optional>
    timeout : timeout until the setTimeout should stop polling (not 100% accurate. It was accurate enough for my code, but if you need exact milliseconds, please refrain from using Date <optional>
    timeoutfunc : function to call on timeout <optional>
*/
function waitUntil(funcCond, readyAction, checkInterval, timeout, timeoutfunc) {
    if (checkInterval == null) {
        checkInterval = 100; // checkinterval of 100ms by default
    }
    var start = +new Date(); // use the + to convert it to a number immediatly
    if (timeout == null) {
        timeout = Number.POSITIVE_INFINITY; // no timeout by default
    }
    var checkFunc = function() {
        var end = +new Date(); // rough timeout estimations by default

        if (end-start > timeout) {
            if (timeoutfunc){ // if timeout function was defined
                timeoutfunc(); // call timeout function
            }
        } else {
            if(funcCond()) { // if condition was met
                readyAction(); // perform ready action function
            } else {
                setTimeout(checkFunc, checkInterval); // else re-iterate
            }
        }
    };
    checkFunc(); // start check function initially
};

This would work perfectly if your functions set a certain condition to true, which you would be able to poll. Plus it comes with timeouts, which offers you alternatives in case your function failed to do something (even within time-range. Think about user feedback!)

eg

doSomething();
waitUntil(function() { return doSomething_value===1;}, doSomethingElse);
waitUntil(function() { return doSomethingElse_value===1;}, doSomethingUseful);

Notes

Date causes rough timeout estimates. For greater precision, switch to functions such as console.time(). Do take note that Date offers greater cross-browser and legacy support. If you don't need exact millisecond measurements; don't bother, or, alternatively, wrap it, and offer console.time() when the browser supports it

참고URL : https://stackoverflow.com/questions/5187968/how-should-i-call-3-functions-in-order-to-execute-them-one-after-the-other

반응형