지연된 객체 란 무엇입니까?


답변:


101

지연된 개체

jQuery 1.5부터 Deferred 객체는 자체 관리 콜백 대기열에 여러 콜백을 등록하고, 적절하게 콜백 대기열을 호출하고, 동기 또는 비동기 함수의 성공 또는 실패 상태를 릴레이하는 방법을 제공합니다.

지연된 방법 :

  • deferred.done ()
    • Deferred 개체가 해결 될 때 호출 할 처리기를 추가합니다.
  • deferred.fail ()
    • Deferred 개체가 거부 될 때 호출 할 처리기를 추가합니다.
  • deferred.isRejected ()
    • Deferred 개체가 거부되었는지 확인합니다.
  • deferred.isResolved ()
    • 지연된 개체가 해결되었는지 확인합니다.
  • deferred.reject ()
    • Deferred 객체를 거부하고 지정된 인수로 failCallback을 호출합니다.
  • deferred.rejectWith ()
    • Deferred 객체를 거부하고 주어진 컨텍스트 및 인수를 사용하여 failCallback을 호출합니다.
  • deferred.resolve ()
    • Deferred 객체를 해결하고 주어진 인수로 doneCallbacks를 호출합니다.
  • deferred.resolveWith ()
    • Deferred 객체를 해결하고 주어진 컨텍스트 및 인수로 doneCallbacks를 호출합니다.
  • deferred.then ()
    • Deferred 개체가 확인되거나 거부 될 때 호출 할 처리기를 추가합니다.

행동 연기 :

$.get("test.php").done(
    function(){ alert("$.get succeeded"); }
);

$.get("test.php")
    .done(function(){ alert("$.get succeeded"); })
    .fail(function(){ alert("$.get failed!"); });

그리고 기존 ajax () 메서드 콜백은 설정에서 선언하는 대신 체인으로 연결할 수있는 것 같습니다.

var jqxhr = $.ajax({ url: "example.php" })
    .success(function() { alert("success"); })
    .error(function() { alert("error"); })
    .complete(function() { alert("complete"); });

Eric Hynds 블로그 게시물의 작업 예 : http://jsfiddle.net/ehynds/Mrqf8/


jqXHR

jQuery 1.5부터 $ .ajax () 메서드는 XMLHTTPRequest 객체의 상위 집합 인 jXHR 객체를 반환합니다. 자세한 내용은 $ .ajax 항목의 jXHR 섹션을 참조하십시오.


에서 JQUERY 1.5을 발표했다 :

지연된 개체

Ajax 모듈의 재 작성과 함께 새로운 기능인 Deferred Objects 가 공개되었습니다 . 이 API를 사용하면 즉시 표시되지 않을 수있는 반환 값 (예 : 비동기 Ajax 요청의 반환 결과)으로 작업 할 수 있습니다. 또한 여러 이벤트 핸들러 (이전에는 Ajax API에서 가능하지 않았던 것)를 연결할 수있는 기능을 제공합니다.

또한 노출 된 jQuery.Deferred를 사용하여 자신 만의 지연된 객체를 만들 수 있습니다. 이 API에 대한 자세한 정보는 Deferred Object 문서 에서 찾을 수 있습니다 .

Eric Hynds는 jQuery 1.5에서 Deferreds 사용 에 대한 좋은 튜토리얼을 작성했습니다 .


19
더 설명해주세요. 나만의 사용자 지정 지연 객체를 생성하려면 어떻게합니까? 어떻게 작동합니까?
user113716

3
사실 나는 진지하다. 이것은 새로운 기능에 대한 좋은 질문입니다. 나는 그들이 어떻게 작동하는지 전혀 모른다. 그리고 나는 StackOverflow가 앞으로 그것에 대해 물어볼 사람들을 위해이 질문을 잘 설명했다면 좋을 것이라고 생각합니다.
user113716

1
업데이트 : 맨 위에 추가 한 "지연됨"의 정의가 실제로 수행하는 작업에 대한보다 명확한보기를 제공한다고 생각합니다. 함수에 전달 된 설정에서 콜백을 선언하는 것보다 콜백을 연결할 수 있다는 것이 더 많은 것 같습니다.
헌터

1
@Hunter 나는 또한 그것이 어떻게 작동하는지에 대한 설명을 원합니다. 이것이 첫 번째 질문이므로 좋은 답변으로 만드십시오!
Raynos

2
몇 가지 주요 이점이 있습니다. 가능한 비동기 작업의 결과를 추상화 할 수 있음, 다양한 유형의 여러 처리기를 바인딩하는 기능, 작업이 해결 된 후에도 처리기를 작업에 바인딩, 여러 비동기 요청의 결과 연결 함께, 조건부로 핸들러 추가 등
ehynds

13

그 다음 그것이 무엇을하는지 말하는 것보다 그것이 무엇을하는지 보여주고 설명 할 것입니다.

jQuery 1.5의 관련 소스 사본. 의견이 대부분 정확하다고 생각합니다.

이것은 유익 할 수 있습니다

// promiseMethods. These are the methods you get when you ask for a promise.
// A promise is a "read-only" version
// fullMethods = "then done fail resolve resolveWith reject rejectWith isResolve    isRejected promise cancel".split(" ")
// As you can see it removes resolve/reject so you can't actaully trigger a
// anything on the deferred object, only process callbacks when it "finishes".
promiseMethods = "then done fail isResolved isRejected promise".split(" "),

// Create a simple deferred (one callbacks list)
/* Class: _Deferred.
 *  methods: done, resolve, resolveWith, isResolved
 *  internal method: cancel
 *
 *  Basically allows you to attach callbacks with the done method.
 *  Then resolve the deferred action whenever you want with an argument.
 *  All the callbacks added with done will be called with the resolved argument
 *  Any callbacks attached after resolvement will fire immediatly.
 *
 *  resolveWith allows you to set the this scope in the callbacks fired.
 *
 *  isResolved just checks whether it's resolved yet.
 *
 *  cancel blocks resolve/resolveWith from firing. the methods added throug
 *  done will never be called
 */
_Deferred: function () {
    var // callbacks list
    callbacks = [],
        // stored [ context , args ]
        // stores the context & args that .resolve was called with
        fired,
        // to avoid firing when already doing so
        firing,
        // flag to know if the deferred has been cancelled
        // in Deferred cancel gets called after the first resolve call
        cancelled,
        // the deferred itself
        deferred = {

            // done( f1, f2, ...)
            done: function () {
                if (!cancelled) {
                    var args = arguments,
                        i, length,
                        // elem in callback list
                        elem,
                        // type of elem in callback list
                        type,
                        // cached context & args for when done is called
                        // after resolve has been
                        _fired;
                    // If resolve has been called already
                    if (fired) {
                        // mark it locally
                        _fired = fired;
                        // set fired to 0. This is neccesary to handle
                        // how done deals with arrays recursively
                        // only the original .done call handles fired
                        // any that unwrap arrays and call recursively
                        // dont handle the fired.
                        fired = 0;
                    }
                    // for each function append it to the callback list
                    for (i = 0, length = args.length; i < length; i++) {
                        elem = args[i];
                        type = jQuery.type(elem);
                        // if argument is an array then call done recursively
                        // effectively unwraps the array
                        if (type === "array") {
                            // def.done([f1, f2, f3]) goes to
                            // def.done(f1, f2, f3) through the apply
                            deferred.done.apply(deferred, elem);
                        } else if (type === "function") {
                            // if its a function add it to the callbacks
                            callbacks.push(elem);
                        }
                    }
                    // if it's already been resolved then call resolveWith using
                    // the cahced context and arguments to call the callbacks
                    // immediatly
                    if (_fired) {
                        deferred.resolveWith(_fired[0], _fired[1]);
                    }
                }
                return this;
            },

            // resolve with given context and args
            resolveWith: function (context, args) {
                                // if its been cancelled then we can't resolve
                                // if it has fired then we can't fire again
                                // if it's currently firing then we can't fire. This check is
                // there because of the try finally block. It ensures we
                // cant call resolve between the try & finally in the catch phase.
                if (!cancelled && !fired && !firing) {
                    firing = 1;
                    // try block because your calling external callbacks
                    // made by the user which are not bugfree.
                                        // the finally block will always run no matter how bad
                                        // the internal code is.
                    try {
                        while (callbacks[0]) {
                            callbacks.shift().apply(context, args);
                        }
                                        // cache the content and arguments taht have been called
                                        // and set firing to false.
                    } finally {
                        fired = [context, args];
                        firing = 0;
                    }
                }
                return this;
            },

            // resolve with this as context and given arguments
            // just maps to resolveWith, this sets the this scope as normal
            // maps to this.promise which is the read only version of Deferred.
            resolve: function () {
                deferred.resolveWith(jQuery.isFunction(this.promise) ? this.promise() : 
this, arguments);
                return this;
            },

            // Has this deferred been resolved?
            // checks whether it's firing or if it has fired.
            isResolved: function () {
                return !!(firing || fired);
            },

            // Cancels the action. To be used internally
            cancel: function () {
                cancelled = 1;
                callbacks = [];
                return this;
            }
        };

    return deferred;
},
/* Class: Deferred.
 *  methods: then, done, fail, resolve, reject, resolveWith, rejectWith, isResolved, 
isRejected, promise
 *
 *  then is a shortcut for both assigning done & fail in one function.
 *
 *  This one has two underlying lists with different semantic meanings. You
 *  can bind to both the done callbacks and the fail callbacks then either
 *  resolve or reject your Deferred object.
 *
 *  You can check whether it has been resolved or rejected. useful to see
 *  Afterwards which one has happened.
 *
 *  Call .promise to return a new object which doesn't have the resolve/reject
 *  methods on it. This means you can only bind to it and not resolve/reject it.
 *  This is effectively read-only.
 *
 */
// Full fledged deferred (two callbacks list)
Deferred: function (func) {
        // the main deferred which deals with the success callbacks
    var deferred = jQuery._Deferred(),
                // the failure deferred which deals with the rejected callbacks
        failDeferred = jQuery._Deferred(),
                // the read only promise is cached.
        promise;
    // Add errorDeferred methods, then and promise
    jQuery.extend(deferred, {
                // def.then([f1, f2, ...], [g1, g2, ...] is a short hand for
                // def.done([f1, f2, ...])
        // def.fail([g1, g2, ...])
        then: function (doneCallbacks, failCallbacks) {
                        // fail exists here because this code will only run after
                        // deferred has been extended.
            deferred.done(doneCallbacks).fail(failCallbacks);
            return this;
        },
                // map def.fail to the second underlying deferred callback list
                // map all the other methods for rejection/failure to the underlying
                // failDeffered object so that Deferred has two callback lists stored
                // internally.
        fail: failDeferred.done,
        rejectWith: failDeferred.resolveWith,
        reject: failDeferred.resolve,
        isRejected: failDeferred.isResolved,
        // Get a promise for this deferred
        // If obj is provided, the promise aspect is added to the object
                // no clue what to do with "i"
        promise: function (obj, i /* internal */ ) {
                        // if no argument is passed then just extend promise
            if (obj == null) {
                                // if cached return the cache.
                if (promise) {
                    return promise;
                }
                                // set promise & arg to be {}
                promise = obj = {};
            }
                        // for each promiseMethods in the read only promise list
            i = promiseMethods.length;
            while (i--) {
                                // set the deferred method on the object
                obj[promiseMethods[i]] = deferred[promiseMethods[i]];
            }
                        // returns the "read-only" deferred without
                        // resolve, resolveWith, reject & rejectWith.
                        // So you cant "resolve" it but only add "done" functions
            return obj;
        }
    });
    // Make sure only one callback list will be used
        // if either resolve or reject is called cancel both.
        // this means that the one that has been called cant be called again
        // and the other one will never be called. So only the done or the fail
        // methods will ever be called
    deferred.then(failDeferred.cancel, deferred.cancel);
        // Don't mess with cancel!
    // Unexpose cancel
    delete deferred.cancel;
    // Call given func if any
        // function argument to be called. This was passed in. Allows you to
        // handle the deferred object after creating a new one, both as this scope
        // and as a new argument.
    if (func) {
        func.call(deferred, deferred);
    }
    return deferred;
},

/* Method: when
 * Arguments: none OR 1 of type(any & !deferred) OR n of type(deferred).
 *
 * If no arguments are passed then it gets resolved immediatly. A good way to
 * call multiple callback functions? Don't really know a good use of $.when()
 *
 * If one argument is passed and its not a deferred object then it resolves
 * immediatly and passes that argument to all the done callbacks attached.
 *
 * if n arguments are passed of type deferred object then the the done callbacks
 * will only fire if all of them succeed. If a single one fails then the
 * fail callbacks fire.
 *
 * Returns a promise read-only deferred object
 */
// Deferred helper
when: function (object) {
    var args = arguments,
        length = args.length,
                // If you pass in a deferred object then set deferred to be the promise
        // if you pass in anything else then set deferred to be a new deferred
        deferred = length <= 1 && object && jQuery.isFunction(object.promise) ?
                object :
                        jQuery.Deferred(),
        // cache the promise
        promise = deferred.promise(),
                // store an array
        resolveArray;

        // if multiple objects are passed in
    if (length > 1) {
                // create an arrey to store of values.
        resolveArray = new Array(length);
                // for each object that we wait on
        jQuery.each(args, function (index, element) {
                        // when that object resolves then
            jQuery.when(element).then(function (value) {
                                // store value in the array or store an array of values in it
                resolveArray[index] = arguments.length > 1 ? slice.call(arguments, 0) : 
value;
                                // if length === 1 then we finished calling them all
                if (!--length) {
                                        // resolve the deferred object with the read only promise
                                        // as context and the resolved values array as the argument
                    deferred.resolveWith(promise, resolveArray);
                }
                        // if any fail then we reject or deferred
            }, deferred.reject);
        });
        // if deferred was newly created but there was only one argument then
    // resolve it immediatly with the argument.
    } else if (deferred !== object) {
        deferred.resolve(object);
    }
        // return the read-only deferred.
    return promise;
},

6
수평 스크롤바가 없다면 훨씬 더 좋을 것입니다. : /
gnarf

@gnarf Problem solved. Btw는 1.5 베타 소스입니다 1.6에서 약간의 변화가 있다고 생각합니다
Raynos

9

내가 틀렸다면 정정하십시오.하지만 최근에는 본질적으로 비동기 태스크 러너라는 것을 클릭했습니다. 약속은 결과 계약으로, 무언가를받을 수 있도록 보장하지만 언제 받을지 보장하지 않습니다.


그래서 새 병에 담긴 오래된 와인!
ankush981

3

Javascript에서 작업하는 동안 함수 호출이 비동기적인 상황이 발생합니다. 그것은 calee 함수 (X라고 말하자)의 흐름이 호출 된 비동기 함수 (Y라고 말하자)를 기다리지 않는다는 것입니다. 전형적인 예는 데이터베이스 또는 HTML 페이지에서 일부 데이터를 가져 오기 위해 서버를 호출하는 경우입니다. 이러한 호출이 비동기식이 아닌 경우 사용자 인터페이스는 서버가 응답 할 때까지 대기합니다. 이러한 비동기 특성은 순서대로 실행하려는 경우 문제를 일으 킵니다. 예를 들어 Y (비동기) 실행이 완료되거나 데이터 가져 오기가 완료된 후에 무언가를 인쇄하려는 경우입니다. 여기서 jQuery는 Deffered Object를 제공합니다. 기본적으로 jQuery는 일반적으로이 상황을 해결하기 위해 작성하는 모든 상용구 코드를 처리했습니다. 다음은 간단한 예입니다.

  $.ajax({
      ...
  }).done(function(){
      //write here what you wish to do when this ajax call is success
  }).fail(function(){
      //write here what you wish to do on failure of this ajax call
  }); //see more on jQuery Deferred page

고유 한 지연 (비동기) 함수를 작성할 수 있습니다.

function DoSomethingTimeConsumingAsynch(){
    var deferred = $.Deferred();

    _.defer(function(){ //I am using underscore, you can also use setTimeout
        ...  
        deferred.resolve();//When the process is done successfully 
        ...
        deferred.reject(); //When the process has failed
    });
    return deferred;
}

//HEre how to use your own asynch function
DoSomethingTimeConsumingAsynch()
.done(function(){
   //this will be invoked on success
})
.fail(function(){
   //this will be invoked on failure
})

도움이 되었기를 바랍니다.

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