Maison  >  Article  >  interface Web  >  Anatomie de l'objet différé JQuery

Anatomie de l'objet différé JQuery

巴扎黑
巴扎黑original
2017-06-26 14:24:201059parcourir

JQuery utilise des objets Deferred pour fournir des fonctions similaires à Promise dans ES2016 (alias. es7).
La fonction de requête AJAX dans JQuery renvoie un objet différé.
Rendez les appels asynchrones plus lisibles et activez une utilisation avancée (spécifiez plusieurs fonctions de rappel/attendez plusieurs requêtes AJAX) en utilisant Defered.

  • Requête AJAX traditionnelle dans JQuery

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

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

Cet article se concentrera sur l'analyse du processus de changement d'état de Deferred/Promise et décrira l'application des objets Deferred dans le codage réel.

Créer un objet différé

Les utilisateurs peuvent utiliser la fonction Deferred pour créer des objets différés

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

Le statut des objets différés

Les objets différés ont les trois états suivants :

  • en attente

  • rejeté

  • résolu

Les objets différés peuvent être convertis de l'état en attente à l'état rejeté ou résolus.
Cette transition d'état est à sens unique, c'est-à-dire une fois l'état de l'objet différé. est rejeté/résolu, l’état de l’objet sera immuable.

Obtenir le statut de l'objet Différé

JQuery propose trois fonctions pour afficher/modifier le statut de l'objet Différé :

  • deferred.state(), return a La chaîne représente le statut de l'objet différé actuel

  • deferred.reject(), définissez le statut de l'objet sur rejeté

  • deferred.resolve(), définissez le statut de l'objet sur rejeté Le statut est défini sur résolu

Le code suivant définit deux objets différés et utilise la résolution/rejet pour modifier leur statut

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"

Fonction de rappel différé

JQuery fournit une méthode pour spécifier la fonction de rappel lorsque l'état de l'objet différé change

Spécifier la fonction de rappel

Utiliser la méthode then

La méthode then accepte deux fonctions comme paramètres. Lorsque l'état de l'objet est résolu, la première fonction sera appelée.
Lorsque le statut de l'objet est rejeté, la deuxième fonction sera appelée.

La première fonction accepte un paramètre, qui est le premier paramètre passé lorsque la fonction defered.resolve est appelée.
La deuxième fonction accepte un paramètre, qui est le premier paramètre passé lorsque la fonction defered.reject est appelée.

  • Utilisez les méthodes then et de résolution

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'});
  • Utilisez then et Méthode de rejet

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

Utiliser la méthode done

Utiliser la méthode done pour spécifier quoi appeler lorsque le statut de l'objet différé est résolu Fonction

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

Utilisez la méthode fail

Utilisez la méthode fail pour spécifier la fonction à appeler lorsque le statut de l'objet différé est rejeté

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

Utilisez la méthode Always

La méthode Always accepte une fonction comme paramètre, qui sera appelée à chaque fois que l'état du Modifications d'objet différées.

Appels en chaîne

Étant donné que les fonctions then/done/fail renvoient toujours des objets de type différé, nous pouvons les utiliser pour spécifier plusieurs fonctions de rappel.
Le suivant L'exemple utilise done/fail pour spécifier plusieurs objets

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

Promise

JQuery fournit également des objets Promise, qui peuvent être obtenus via la méthode promise de l'objet Deferred L'objet Promise pour cet objet. =
L'objet Promise présente les caractéristiques suivantes :

  • L'objet Promise n'a pas la méthode reject/resolve

  • Le statut de l'objet Promise est le même car les objets Deferred restent cohérents

  • Les objets Promise obtiennent le statut de Deferred qui leur est lié via la state() méthode

  • Les objets Proimse peuvent également être utilisésthen/done/fail pour spécifier la fonction de rappel

  • Promise peut appeler la méthode promise pour s'obtenir

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

La différence entre then et done/fail

done/fail renvoie l'objet différé lui-même
La méthode then renvoie un nouvel objet Promise

Utilisation done/ La méthode fail renvoie un objet 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]});

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn