什么是延期对象?

jQuery 1.5增加了“延迟对象”。 他们是什么,他们到底做了什么?

延迟对象

从jQuery 1.5开始,Deferred对象提供了一种将多个callback注册到自我pipe理的callback队列中,根据需要调用callback队列以及中继任何同步或asynchronous函数的成功或失败状态的方法。

延期方法:

  • deferred.done()
    • 添加处理程序以在parsingDeferred对象时调用。
  • deferred.fail()
    • 添加要在Deferred对象被拒绝时调用的处理程序。
  • deferred.isRejected()
    • 确定一个Deferred对象是否被拒绝。
  • deferred.isResolved()
    • 确定一个Deferred对象是否已经被parsing。
  • deferred.reject()
    • 拒绝Deferred对象并使用给定的参数调用任何failCallback。
  • deferred.rejectWith()
    • 拒绝Deferred对象并使用给定的上下文和参数调用任何failCallback。
  • deferred.resolve()
    • parsing一个Deferred对象,并用给定的参数调用任何doneCallbacks。
  • deferred.resolveWith()
    • parsingDeferred对象,并用给定的上下文和参数调用任何doneCallbacks。
  • deferred.then()
    • 添加处理程序以在Deferred对象被parsing或拒绝时调用。

推迟行动:

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

看来,现有的ajax()方法callback可以链接,而不是在设置中声明:

 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()方法返回jXHR对象,它是XMLHTTPRequest对象的超集。 有关更多信息,请参阅$ .ajax条目的jXHR部分


从JQUERY 1.5发布 :

延迟对象

随着Ajax模块的重写,引入了一个新的function,这个function也是公开的: Deferred Objects 。 这个API允许您使用可能不会立即出现的返回值(例如来自asynchronousAjax请求的返回结果)。 此外,它使您能够附加多个事件处理程序(Ajax API中以前不可能的东西)。

另外,你可以使用公开的jQuery.Deferred创build自己的延期对象。 有关此API的更多信息可以在延迟对象文档中find。

Eric Hynds写了一篇关于在jQuery 1.5中使用Deferreds的很好的教程。

而是告诉你它做了什么,我会告诉你它做了什么,并解释它。

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; }, 

纠正我,如果我错了,但它最近点击我,它本质上是一个asynchronous任务亚军。 承诺是一个结果合同,确保你得到…的东西,但没有保证你什么时候得到它。

在Javascript中工作时,遇到函数调用asynchronous的情况。 这就是Calee函数的(比方说X)stream程不会等待被调用的asynchronous函数(假设是Y)。 典型的例子是当我们调用服务器从数据库或HTML页面获取一些数据时。 如果这些调用不是asynchronous的,则用户界面将被卡住等待服务器响应。 当你想按顺序执行的时候,这种asynchronous的特性会导致一个问题,例如,你想在Y(asynchronous)执行或者完成数据提取之后打印一些东西。 这里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 

您可以编写自己的延迟(asynchronous)函数

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

我希望这有助于。