您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

JQuery Deferred 对象剖析

2025/10/20 14:29:22发布35次查看
jquery 中利用 deferred 对象提供类似 es2016(aka. es7) 中 promise 的功能。
jquery 中的 ajax 请求函数返回的就是 deferred 对象。
通过使用 defered 让异步调用更加可读,实现高级的用法(指定多个回调函数/等待多个 ajax 请求)。
jquery中传统的ajax请求
$.getjson('url', data=>{// 处理返回的json数据console.log(data);}, err=>{// 处理出错信息console.log(err.status);})
使用 deferred 的ajax请求
$.getjson('url').done(data=>{console.log(data);}).fail(err=>{console.log(err.status);});
这篇文章会着重分析 deferred/promise 的状态变化过程,并讲述 deferred 对象在实际编码中的应用。
创建 deferred用户可以使用 deferred 函数来创建 deferred 对象
var d1 = $.deferred();console.log(d1.state());
deferred 对象的状态deferred 对象有以下三种状态
pending
rejected
resolved
deferred 对象可以从pending状态转换到rejected状态或者resolved.
这种状态的转换是单向的,也就是说一旦deferred对象的状态是 rejected/resolved, 对象的状态将不可变。
得到 deferred 对象的状态jquery 提供了三个函数来查看/修改deferred对象的状态:
deferred.state(), 返回一个字符串表示当前 deferred 对象的状态
deferred.reject(), 将对象的状态设置为 rejected
deferred.resolve(), 将对象的状态设置为 resolved
下面的代码定义了两个 deferred 对象,并分别使用 resolve/reject 改变他们的状态
let d1 = $.deferred();console.log(d1.state()); // "pending"d1.resolve();console.log(d1.state()); // "resolved"let d2 = $.deferred();console.log(d2.state()); // "pending"d2.reject();console.log(d2.state()); // "rejected"
deferred 回调函数jquery 提供了方法来指定当 deferred 对象状态发生变化时的回调函数
指定回调函数使用 then 方法then 方法接受两个函数作为参数,当对象的状态变成 resolved, 第一个函数会被调用。
当对象的状态变成 rejected, 第二个函数会被调用。
第一个函数接受一个参数,该参数是 defered.resolve 函数被调用时传递的第一个参数。
第二个函数接受一个参数,该参数是 defered.reject 函数被调用时传递的第一个参数。
使用 then 和 resolve 方法
var d1 = $.deferred();// 注册回调函数d1.then(function(data){console.log('first function: ' + data.state);}, function(err){console.log('second function: ' + err);});// 做一些耗时的操作// 改变 deferred 对象状态为 resolved// 回调函数将被调用,打印信息:first function: successedd1.resolve({state: 'successed'});
使用 then 和 reject 方法
var d2 = $.deferred();// 注册回调函数d2.then(function(data){console.log('first function: ' + data.state);}, function(err){console.log('second function: ' + err.state);});// 改变 deferred 对象状态为 rejected// 回调函数将被调用,打印信息:second function: failedd2.reject({state: 'failed'});
使用 done 方法使用 done 方法可以指定当 deferred 对象状态变成 resolved 时调用的函数
var deferred = $.deferred();deferred.done(function(data){console.log('done: ' + data.state);});deferred.resolve({state: 'successed'});
使用 fail 方法使用 fail 方法可以指定当 deferred 对象状态变成 rejected 时调用的函数
var deferred = $.deferred();deferred.fail(function(err){console.log('fail: ' + err.state);})deferred.resolve({state: 'failed'});
使用 always 方法always 方法接受一个函数作为参数,只要 deferred 对象的状态发生变化,该函数都会被调用。
链式调用因为 then/done/fail 函数返回的仍然是类 deferred 对象,所以我们可以使用他们来指定多个回调函数.
下面这个例子用 done/fail 来指定多个
var deferred = $.deferred();deferred.done(data=>{// do something}).done(data=>){// do something}.fail(err=>{// handle the error}).always(()=>{// clean the environment})
promise 对象jquery 还提供了 promise 对象,可以通过 deferred 对象的 promise 方法来获取该对象的 promise 对象。=
promise 对象有以下特点:
promise 对象没有 reject/resolve 方法
promise 对象的状态跟 deferred 对象保持一致
promise 对象通过 state() 方法获取跟它绑定的 deferred 的状态
proimse 对象也可以使用 then/done/fail 方法来指定回调函数
promise 可以调用 promise 方法获取它自身
var deferred = $.deferred();var promise = deferred.promise();deferred.reject();console.log(deferred.state()); // rejectedconsole.log(promise.state()); // rejectedconsole.log(promise.promise() === promise); // true, promise 对象的 promis() 方法返回的是它自己
then 和 done/fail 的差异done/fail 返回的是 deferred 对象自身
then 方法返回的是一个新的 promise 对象
使用 done/fail 方法返回 deferred 对象var d1 = $.deferred();var d2 = d1.done();var d3 = d1.fail();console.log(d1 === d2); // trueconsole.log(d1 === d3); // true
使用 then 方法返回 promise 对象使用 then 方法我们需要明白的几个关键点是:
方法返回的是 promise 对象,该对象没有 resolve/reject 方法。deferred 对象的 then 方法, 会创建一个新的 deferred 对象,并返回新 deferred 对象的 promise 对象。
而且 then 方法返回的对象 跟 deferred 对象的 promise 对象不相等, 多次调用 then 对象会产生多个 deferred 对象。
下面的例子对比了多次调用 then 方法产生的 promise 对象
var d1 = $.deferred();var p2 = d1.then(); // 调用 then 方法返回一个 promise 对象var p3 = d1.then(); // 调用 then 方法返回一个新的 promise 对象console.log('reject' in d1); // false, 查看 then 方法返回的对象中是否有 reject 方法console.log('reject' in p2); // false, 查看 then 方法返回的对象中是否有 reject 方法console.log(p2 === d1); // false, 检查 d1 是否与 p2 相等console.log(p2 === d1.promise()); // false, 查看 d1 的 promise 是否与 p2 相等console.log(p2 === p3); // false, p2 和 p3 的值不同
deferred 对象的状态发生改变后,then 方法产生的 promise 对象的状态不会立即发生变化deferred 对象状态发生变化后, 等待一段时间后 then 方法产生的 promise 对象的状态才会发生相应的变化
var deferred = $.deferred();var new_promise = deferred.then();deferred.reject('reject')console.log(`d1 state: ${deferred.state()}`); // rejectedconsole.log(`new_promise state: ${new_promise.state()}`); // pendingsettimeout(`console.log("new_promise state after 100 miliseconds: ${new_promise.state()}")`, 100); // 100 毫秒后, new_promise 的状态变成了 rejected
发生了什么deferred 对象的状态发生改变后,then 方法产生的 promise 对象的状态并没有立即发生变化, 而是等待了一段时间后才改变。
这段时间内,发生了什么那?
我们以调用 deferred 对象的 resolve 方法作为例子来说明。 调用 reject 方法的情况与此类似。
首先假设我们构造了deferred 对象 d1
然后调用 then 方法,并且传入两个函数作为参数 fun1, fun2: var p2 = d1.then(fun1, fun2)
调用 d1.resolve(data) 方法将 d1 的状态设置为 resolved, 此时d1 的状态是 resolved, p2 的状态是 pending
fun1 会被调用, 参数为 d1.resolve 方法的参数: var new_data = fun1(data)
假设 p2 对应的 deferred 对象是 d2.
d2 的 resolve 方法会被调用, 参数为 fun1 的返回值: d2.resolve(new_data)
p2 的状态变为 resolved
p2 的回调函数会被调用
下面的代码展示了 then 方法产生的 promise 对象的状态变化。以及如何给回调函数传递参数
var d1 = $.deferred();function fun1(data){console.log(`p2 state in fun1: ${p2.state()}`);console.log(`data in fun1: ${data}`);return data * 3;}function fun2(error){return 'new data from fun2';}var p2 = d1.then(fun1, fun2);p2.done(data=>{console.log(`p2 state in done: ${p2.state()}`);console.log(`data in done: ${data}`);});d1.resolve(10);/* 屏幕输出为p2 state in fun1: pendingdata in fun1: 10p2 state in done: resolveddata in done: 30*/
在网页中使用 deferred自定义函数明白了 deferred 的原理,我们就可以使用 deferred.
下面一段代码定义了一个函数, 在函数中定义了一些耗时的操作。
函数返回 promise 对象, 可以使用 done/fail/then 注册回调函数
function say_hello(){// 创建 deferred 对象var deferred = $.deferred();// 做一些耗时的操作,操作完成后调用 resolve 或者 reject 函数结束。// 我们用 settimeout 函数模拟一段耗时操作:// 等待五秒钟后,调用 deferred 的 resolve 方法来改变状态settimeout(deferred.resolve.bind(deferred, 'hello world'), 5000);// 也可以使用 ajax 操作/* $.getjson('/api/names').done(data=>{ if(data.state == 'successed'){ deferred.resolve(data); }else{ deferred.reject(data); } }); */return deferred.promise(); // 返回 promise 对象, 防止外界对 deferred 对象的状态进行改变}// 调用 say_hello函数,并使用 done/fail/then 方法注册回调函数say_hello().done(msg=>{console.log(msg);});
$.when跟 es2016 中 prmomise.all 函数类似。
jquery 提供了 when 函数, 它可以接受多个 deferred/promise 对象作为参数。并返回一个 promise 对象。
新的 promise 对象会等待参数中所有的对象状态变为 resolved/reject。
如果参数中任何一个对象的状态变为 rejected, 那么 promise 对象的状态变为 rejected。 否则变为 resolved。
// 创建一个函数,如果参数大于500, 则将内置的 deferred 对象状态变为 resolved// 如果参数小于500, 则将内置的 deferred 对象状态变为 rejectedfunction get_promise(delay){// 创建 deferred 对象var deferred = $.deferred();if(delay > 500){settimeout(deferred.resolve.bind(deferred, delay/100), delay);}else{settimeout(deferred.reject.bind(deferred, delay/100), delay);}return deferred.promise(); // 返回 promise 对象}// 如果任一参数状态转变为 rejected, when 函数产生的 promise 对象状态会理解变为 rejected。// 并将第一个 deferred 对象的错误信息传递给回调函数$.when(get_promise(800), get_promise(100), get_promise(300)).fail(error=>{console.log(error); // 1});// 否则 when 函数会等待所有的 deferred 对象状态变为 resolved, 并将所有 deferred 对象的返回值依次传递给回调函数$.when(get_promise(900), get_promise(600), get_promise(1000)).done((d1, d2, d3)=>{console.log(d1); // 9console.log(d2); // 6console.log(d3); // 10});$.when(get_promise(800), get_promise(900), get_promise(1000)).done((...datas)=>{console.log(datas); // [8, 9, 10]});
以上就是jquery deferred 对象剖析的详细内容。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product