>  기사  >  웹 프론트엔드  >  JQuery 지연 객체 분석

JQuery 지연 객체 분석

巴扎黑
巴扎黑원래의
2017-06-26 14:24:201060검색

JQuery는 Deferred 객체를 사용하여 ES2016(또는 es7)의 Promise와 유사한 기능을 제공합니다.
JQuery의 AJAX 요청 함수는 Deferred 객체를 반환합니다.
Defered를 사용하여 비동기 호출을 더 읽기 쉽게 만들고 고급 사용(여러 콜백 함수 지정/여러 AJAX 요청 대기)을 활성화합니다. heferred rreeee

    를 사용한 jQuery
  • $.getJSON('url', data=>{// 处理返回的JSON数据console.log(data);}, err=>{// 处理出错信息console.log(err.status);})
    ajax 요청의 전통적인 ajax 요청이 기사는 연기/약속의 국가 변화 과정 분석에 중점을두고 국가 변화 과정을 설명하는 데 중점을 둡니다. 실제 코딩에서의 지연된 객체 응용 프로그램.
  • Create Deferred

  • 사용자는 Deferred 함수를 사용하여 지연된 객체를 생성할 수 있습니다
$.getJSON('url').done(data=>{console.log(data);}).fail(err=>{console.log(err.status);});

지연된 객체의 상태

지연된 객체에는 다음 세 가지 상태가 있습니다

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

    pending
  • 거부됨
resolved


Deferred 객체는 보류 상태에서 거부됨 상태로 전환되거나 해결될 수 있습니다.

이 상태 전환은 단방향입니다. 즉, Deferred 객체의 상태가 거부되면/ 해결되면 객체의 상태는 변경할 수 없게 됩니다.

Deferred 객체의 상태 가져오기
JQuery는 Deferred 객체의 상태를 보거나 수정하는 세 가지 함수를 제공합니다.🎜🎜🎜🎜deferred.state()는 현재 Deferred 객체를 나타내는 문자열을 반환합니다. 객체 상태 🎜🎜🎜🎜deferred.reject(), 객체 상태를 거부됨🎜🎜🎜🎜deferred.resolve()으로 설정, 객체 상태를 해결됨🎜 🎜 🎜🎜다음 코드는 두 개의 Deferred 객체를 정의하고 확인/거부를 사용하여 각각 상태를 변경합니다🎜🎜
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() 方法返回的是它自己
🎜🎜Deferred 콜백 함수🎜🎜JQuery는 Deferred 객체의 상태가 변경될 때 콜백 함수를 지정하는 메서드를 제공합니다🎜 🎜지정 콜백 함수🎜

then 메소드 사용

🎜then 메소드는 객체의 상태가 해결되면 두 함수를 매개변수로 받습니다. 🎜객체의 상태가 거부되면 두 번째 함수가 호출됩니다. 🎜🎜첫 번째 함수는 defered.resolve 함수가 호출될 때 전달되는 첫 번째 매개 변수인 하나의 매개 변수를 허용합니다. 🎜두 번째 함수는 defered.reject 함수가 호출될 때 전달되는 첫 번째 매개변수인 하나의 매개변수를 허용합니다. 🎜
🎜🎜🎜then 사용 및 메서드 해결🎜🎜🎜🎜
var d1 = $.Deferred();var d2 = d1.done();var d3 = d1.fail();console.log(d1 === d2); // trueconsole.log(d1 === d3); // true
🎜🎜🎜🎜then 및 거부 메서드 사용🎜🎜🎜🎜
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 的值不同
🎜

완료 메서드 사용

🎜완료 메서드 사용 지연된 객체 상태가 해결될 때 호출할 함수를 지정할 수 있습니다🎜
🎜
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
🎜

실패 메서드 사용

🎜실패 메서드를 사용하여 다음과 같은 경우 호출할 함수를 지정하세요. 지연된 객체 상태가 거부됩니다. 함수 🎜
🎜
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*/
🎜

항상 메소드 사용

🎜항상 메소드는 함수를 매개변수로 허용하며, 이는 상태가 바뀔 때마다 호출됩니다. 지연된 객체 변경. 🎜
🎜연쇄 호출🎜🎜then/done/fail 함수는 여전히 지연된 객체를 반환하기 때문에 이를 사용하여 여러 콜백 함수를 지정할 수 있습니다.🎜다음 예에서는 done/fail을 사용하여 여러 🎜🎜
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);});
🎜을 지정합니다. 🎜Promise 객체🎜🎜JQuery도 Promise 객체를 제공하는데, Deferred 객체의 promise 메소드를 통해 해당 객체의 Promise 객체를 얻을 수 있습니다. =🎜Promise 개체에는 다음과 같은 특징이 있습니다. 🎜🎜🎜🎜Promise 개체에는 reject/resolve 메서드가 없습니다.🎜🎜🎜🎜Promise 개체의 상태는 다음과 같습니다. Deferred 객체와 일치🎜🎜🎜🎜 Promise 객체는 state() 메서드를 통해 자신에 바인딩된 Deferred의 상태를 얻습니다🎜🎜🎜🎜Proimse 객체는 then을 사용할 수도 있습니다. code>/done/ fail 메소드를 사용하여 콜백 함수를 지정합니다🎜🎜🎜🎜Promise는 Promise 메소드를 호출하여 자기 자신을 얻을 수 있습니다🎜🎜🎜🎜
// 创建一个函数,如果参数大于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]});
🎜🎜그런 다음 차이점은 done/fail🎜🎜done/fail은 Deferred 객체 자체를 반환합니다. 🎜Then 메소드는 새로운 Promise 객체를 반환합니다.🎜🎜done/fail 메소드를 사용하여 Deferred 객체를 반환합니다.🎜🎜rrreee🎜

使用 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 지연 객체 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.