Heim  >  Artikel  >  Web-Frontend  >  Anatomie des verzögerten JQuery-Objekts

Anatomie des verzögerten JQuery-Objekts

巴扎黑
巴扎黑Original
2017-06-26 14:24:201123Durchsuche

JQuery verwendet verzögerte Objekte, um ähnliche Funktionen wie Promise in ES2016 (auch bekannt als es7) bereitzustellen.
Die AJAX-Anfragefunktion in JQuery gibt ein Deferred-Objekt zurück.
Machen Sie asynchrone Aufrufe besser lesbar und ermöglichen Sie eine erweiterte Verwendung (mehrere Rückruffunktionen angeben/auf mehrere AJAX-Anfragen warten), indem Sie Defered verwenden.

  • Traditionelle AJAX-Anfrage in JQuery

$.getJSON('url', data=>{// 处理返回的JSON数据console.log(data);}, err=>{// 处理出错信息console.log(err.status);})
  • AJAX-Anfrage mit Deferred

$.getJSON('url').done(data=>{console.log(data);}).fail(err=>{console.log(err.status);});

Dieser Artikel konzentriert sich auf die Analyse des Zustandsänderungsprozesses von Deferred/Promise und beschreibt die Anwendung von Deferred-Objekten in der tatsächlichen Codierung.

Zurückgestellt erstellen

Benutzer können die Funktion Deferred verwenden, um zurückgestellte Objekte zu erstellen

var d1 = $.Deferred();console.log(d1.state());

Der Status zurückgestellter Objekte

Zurückgestellte Objekte haben die folgenden drei Zustände:

  • ausstehend

  • abgelehnt

  • aufgelöst

Zurückgestellte Objekte können vom Status „Ausstehend“ in den Status „Abgelehnt“ umgewandelt oder gelöst werden.
Dieser Statusübergang erfolgt in eine Richtung, d. h. sobald der Status des zurückgestellten Objekts erreicht ist abgelehnt/aufgelöst wird, bleibt der Zustand des Objekts unveränderlich.

Status des verzögerten Objekts abrufen

JQuery bietet drei Funktionen zum Anzeigen/Ändern des Status des verzögerten Objekts:

  • deferred.state(), return a Die Zeichenfolge stellt den Status des aktuellen verzögerten Objekts dar

  • deferred.reject(), setzt den Status des Objekts auf „Abgelehnt“

  • deferred.resolve(), setzen Sie den Status des Objekts auf „Abgelehnt“. Der Status wird auf „Gelöst“ gesetzt

Der folgende Code definiert zwei zurückgestellte Objekte und verwendet „Auflösen/Ablehnen“, um ihren Status zu ändern

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"

Verzögerte Rückruffunktion

JQuery bietet eine Methode zum Angeben der Rückruffunktion, wenn sich der Status des verzögerten Objekts ändert

Geben Sie die Rückruffunktion an

Verwenden die then-Methode

Die then-Methode akzeptiert zwei Funktionen als Parameter. Wenn der Zustand des Objekts aufgelöst wird, wird die erste Funktion aufgerufen.
Wenn der Status des Objekts „Abgelehnt“ wird, wird die zweite Funktion aufgerufen.

Die erste Funktion akzeptiert einen Parameter. Dies ist der erste Parameter, der beim Aufruf der Funktion defered.resolve übergeben wird.
Die zweite Funktion akzeptiert einen Parameter. Dies ist der erste Parameter, der beim Aufruf der Funktion defered.reject übergeben wird.

  • Verwenden Sie dann und lösen Sie die Methoden auf

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'});
  • Verwenden Sie dann und Methode „Ablehnen“

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

Methode „Done“ verwenden

Methode „Done“ verwenden, um anzugeben, was aufgerufen werden soll, wenn der zurückgestellte Objektstatus aufgelöst wird Funktion

var deferred = $.Deferred();deferred.done(function(data){console.log('Done: ' + data.state);});deferred.resolve({state: 'successed'});

Verwenden Sie die Fail-Methode

Verwenden Sie die Fail-Methode, um die Funktion anzugeben, die aufgerufen werden soll, wenn der zurückgestellte Objektstatus abgelehnt wird

var deferred = $.Deferred();deferred.fail(function(err){console.log('Fail: ' + err.state);})deferred.resolve({state: 'failed'});

Verwenden Sie die Always-Methode

Die Always-Methode akzeptiert eine Funktion als Parameter, die immer dann aufgerufen wird, wenn der Status der Verzögerte Objektänderungen.

Kettenaufrufe

Da die Then/Done/Fail-Funktionen immer noch verzögerte Objekte zurückgeben, können wir sie verwenden, um mehrere Rückruffunktionen anzugeben.
Das Folgende Das Beispiel verwendet done/fail, um mehrere

var deferred = $.Deferred();deferred.done(data=>{// Do something}).done(data=>){// Do something}.fail(err=>{// Handle the error}).always(()=>{// Clean the environment})

Promise-Objekte anzugeben

JQuery stellt auch Promise-Objekte bereit, die über die promise-Methode des Deferred-Objekts abgerufen werden können Das Promise-Objekt für dieses Objekt. =
Das Promise-Objekt hat die folgenden Eigenschaften:

  • Das Promise-Objekt verfügt nicht über die reject/resolve-Methode

  • Der Status des Promise-Objekts ist derselbe wie bei verzögerten Objekten, die konsistent bleiben

  • Promise-Objekte erhalten den Status des an sie gebundenen Deferred über die state()-Methode

  • Proimse-Objekte können auch verwendet werdenthen/done/fail Methode zum Angeben der Rückruffunktion

  • Promise kann die Promise-Methode aufrufen, um sich selbst abzurufen

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() 方法返回的是它自己

Der Unterschied zwischen then und done/fail

done/fail gibt das Deferred-Objekt selbst zurück
Die then-Methode gibt zurück ein neues Promise-Objekt

Verwendung erledigt/ Die Fail-Methode gibt ein verzögertes Objekt zurück

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

Das obige ist der detaillierte Inhalt vonAnatomie des verzögerten JQuery-Objekts. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn