Maison > interface Web > js tutoriel > Comprendre comment utiliser Promise.race() et Promise.any()

Comprendre comment utiliser Promise.race() et Promise.any()

青灯夜游
Libérer: 2020-12-21 09:32:08
avant
3846 Les gens l'ont consulté

Comprendre comment utiliser Promise.race() et Promise.any()

Recommandations associées : "Tutoriel vidéo javascript"

Depuis sa sortie en 1996, JS ne cesse de s'améliorer. Avec de nombreuses améliorations dans les versions ECMAScript, la version la plus récente est ES2020. Une mise à jour importante de JS est Promise, publiée sous le nom ES6 en 2015.

Qu'est-ce que la promesse ?

Définition MDN de Promise : les objets Promise sont utilisés pour représenter l'achèvement final (ou l'échec) d'une opération asynchrone et sa valeur de résultat. Cela peut paraître un peu trop compliqué pour les débutants.

Un aîné étranger a expliqué Promises ainsi : "Imaginez que vous êtes un enfant. Votre mère vous promet qu'elle vous achètera un nouveau téléphone portable la semaine prochaine

Vous ne le ferez pas." découvrez si vous recevez ce téléphone avant la semaine prochaine. Soit votre mère vous achètera un tout nouveau téléphone, soit elle ne vous l'achètera pas parce qu'elle est mécontente.

C'en est unPromise. Un Promise a trois états. Ils sont :

  1. En attente : vous ne savez pas si vous pouvez obtenir ce téléphone
  2. Exécuté : maman est heureuse et l'a acheté pour vous
  3. Rejeté : maman Je suis désolé, je ne l'achèterai pas pour vous

C'est le moyen le plus rapide de comprendre l'exemple de Promise que j'ai entendu jusqu'à présent.

Si vous n’avez pas encore commencé à apprendre Promise, je vous recommande de le faire.

Promise contient plusieurs méthodes intégrées très utiles. Aujourd'hui, nous présentons principalement ces deux méthodes.

  • Promise.race() - Sorti avec ES6
  • Promise.any() - Toujours en proposition de phase 4

Promise.race()

a été initialement publiée lorsque Promise a été introduite dans ES6. Cette méthode nécessite un

comme paramètre. La méthode Promise.race()iterable

renvoie une promesse qui est résolue ou rejetée une fois que l'un des

de l'itérateur est résolu ou rejeté. Promise.race(iterable)promise Contrairement à la méthode

, la méthode

se concentre sur la question de savoir si la promesse a été résolue, qu'elle ait été résolue ou rejetée. Promise.any()Promise.race()Syntaxe

Promise.race(iterable)
Copier après la connexion

Paramètres

— Objet itérable, similaire à Array. les objets itérables implémentent la méthode

. iterableSymbol.iteratorValeur de retour

Une promesse

en attente

Chaque fois qu'une promesse dans une itération donnée est résolue ou rejetée, prend la valeur de la première promesse comme valeur, analysant ou rejetant ainsi de manière asynchrone (une fois la pile vide). Remarque

Comme les paramètres acceptent

, nous pouvons transmettre certaines valeurs, comme des valeurs primitives, ou même des objets dans un tableau. Dans ce cas, la méthode

renverra le premier objet non promis transmis. Cela est principalement dû au fait que le comportement de la méthode est de renvoyer la valeur dès que la valeur est disponible (lorsque la promesse est satisfaite). iterablerace De plus, si une promesse déjà résolue est transmise dans

, la méthode

sera résolue à la première de cette valeur. Si un iterable vide est passé, la méthode Promise.race() sera toujours en attente. IterableraceExemples

const promise1 = new Promise((resolve, reject) => {
    setTimeout(resolve, 500, 'promise 1 resolved');
});

const promise2 = new Promise((resolve, reject) => {
    setTimeout(reject, 100, 'promise 2 rejected');
});

const promise3 = new Promise((resolve, reject) => {
    setTimeout(resolve, 200, 'promise 3 resolved')
});

(async () => {
    try {
        let result = await Promise.race([promise1, promise2, promise3]);
        console.log(result);
    } catch (err) {
        console.error(err);
    }
})();
  // 输出- "promise 2 rejected"
  // 尽管promise1和promise3可以解决,但promise2拒绝的速度比它们快。
  // 因此Promise.race方法将以promise2拒绝
Copier après la connexion

Cas d'utilisation réels

Maintenant, vous vous demandez peut-être, quand utilisons-nous Promise.race() dans la pratique ? Venez jeter un oeil.

Afficher l'animation de chargement lors de la demande de données

Il est très courant d'utiliser l'animation de chargement en développement. Lorsque le temps de réponse des données est long, si l'animation de chargement n'est pas utilisée, il semblera qu'il n'y a pas de réponse. Mais parfois, la réponse est trop rapide. Nous devons ajouter un très petit délai lors du chargement de l'animation, ce qui donnera l'impression à l'utilisateur que je demande fréquemment. Pour y parvenir, utilisez simplement la méthode

comme indiqué ci-dessous.

function getUserInfo(user) {
  return new Promise((resolve, reject) => {
    // had it at 1500 to be more true-to-life, but 900 is better for testing
    setTimeout(() => resolve("user data!"), Math.floor(900*Math.random()));
  });
}

function showUserInfo(user) {
  return getUserInfo().then(info => {
    console.log("user info:", info);
    return true;
  });
}

function showSpinner() {
  console.log("please wait...")
}

function timeout(delay, result) {
  return new Promise(resolve => {
    setTimeout(() => resolve(result), delay);
  });
}
Promise.race([showUserInfo(), timeout(300)]).then(displayed => {
  if (!displayed) showSpinner();
});
Copier après la connexion
Promise.race()Promesse annulée

Dans certains cas, nous devons annuler la promesse. Dans ce cas, nous pouvons également utiliser la méthode

:

function timeout(delay) {
  let cancel;
  const wait = new Promise(resolve => {
    const timer = setTimeout(() => resolve(false), delay);
    cancel = () => {
      clearTimeout(timer);
      resolve(true);
    };
  });
  wait.cancel = cancel;
  return wait;
}


function doWork() {
  const workFactor = Math.floor(600*Math.random());
  const work = timeout(workFactor);
  
  const result = work.then(canceled => {
    if (canceled)
      console.log('Work canceled');
    else
      console.log('Work done in', workFactor, 'ms');
    return !canceled;
  });
  result.cancel = work.cancel;
  return result;
}

function attemptWork() {
  const work = doWork();
  return Promise.race([work, timeout(300)])
    .then(done => {
      if (!done)
        work.cancel();
      return (done ? 'Work complete!' : 'I gave up');
  });
}

attemptWork().then(console.log);
Copier après la connexion
. Promise.race()Requêtes par lots pour une exécution longue

Chris Jensen

a un cas d'utilisation intéressant pour la méthode . Il a utilisé la méthode pour regrouper les requêtes de longue durée. De cette façon, ils peuvent maintenir le nombre de requêtes parallèles fixe. race()

const _ = require('lodash')

async function batchRequests(options) {
    let query = { offset: 0, limit: options.limit };

    do {
        batch = await model.findAll(query);
        query.offset += options.limit;

        if (batch.length) {
            const promise = doLongRequestForBatch(batch).then(() => {
                // Once complete, pop this promise from our array
                // so that we know we can add another batch in its place
                _.remove(promises, p => p === promise);
            });
            promises.push(promise);

            // Once we hit our concurrency limit, wait for at least one promise to
            // resolve before continuing to batch off requests
            if (promises.length >= options.concurrentBatches) {
                await Promise.race(promises);
            }
        }
    } while (batch.length);

    // Wait for remaining batches to finish
    return Promise.all(promises);
}

batchRequests({ limit: 100, concurrentBatches: 5 });
Copier après la connexion
Promise.race()Promise.any()

reçoit un

objet itérable, et tant que l'un des Promise.any() réussit, il renvoie le Promise réussi. Si aucun des promise de l'objet itérable ne réussit (c'est-à-dire que tous les promise échouent/rejetent), une promesse échouée et une instance de type promise sont renvoyées. Il s'agit d'une sous-classe d'Error et est utilisée pour la conversion. une seule erreur est regroupée. Essentiellement, cette méthode est à l’opposé de promises. AggregateError

注意! Promise.any() 方法依然是实验性的,尚未被所有的浏览器完全支持。它当前处于 TC39 第四阶段草案(Stage 4)

语法

Promise.any(iterable);
Copier après la connexion

参数

iterable — 个可迭代的对象, 例如 Array。

返回值

  • 如果传入的参数是一个空的可迭代对象,则返回一个 已失败(already rejected) 状态的 Promise
  • 如果传入的参数不包含任何 promise,则返回一个 异步完成 (asynchronously resolved)的 Promise。
  • 其他情况下都会返回一个处理中(pending) 的 Promise。 只要传入的迭代对象中的任何一个 promise 变成成功(resolve)状态,或者其中的所有的 promises 都失败,那么返回的 promise 就会 异步地(当调用栈为空时) 变成成功/失败(resolved/reject)状态。

说明

这个方法用于返回第一个成功的 promise 。只要有一个 promise 成功此方法就会终止,它不会等待其他的 promise 全部完成。

不像 Promise.all() 会返回一组完成值那样(resolved values),我们只能得到一个成功值(假设至少有一个 promise 完成)。当我们只需要一个 promise 成功,而不关心是哪一个成功时此方法很有用的。

同时, 也不像 Promise.race() 总是返回第一个结果值(resolved/reject)那样,这个方法返回的是第一个 成功的 值。这个方法将会忽略掉所有被拒绝的 promise,直到第一个 promise 成功。

事例

const promise1 = new Promise((resolve, reject) => {
  setTimeout(reject, 100, 'promise 1 rejected');
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 400, 'promise 2 resolved at 400 ms');
});

const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 700, 'promise 3 resolved at 800 ms');
});

(async () => {
  try {
    let value = await Promise.any([promise1, promise2, promise3]);
    console.log(value);
  } catch (error) {
    console.log(error);
  }
})();

//Output - "promise 2 resolved at 400 ms"
Copier après la connexion

从上面代码注意到Promise.any()主要关注解析的值。 它会忽略在100毫秒时拒绝的promise1,并考虑在400毫秒后解析的promise2的值。

真实用例

从最快的服务器检索资源

假设访问我们网站的用户可能来自全球各地。如果我们的服务器基于单个位置,那么响应时间将根据每个用户的位置而不同。但是如果我们有多个服务器,可以使用能够产生最快响应的服务器。在这种情况下,可以使用Promise.any()方法从最快的服务器接收响应。

原文地址:https://blog.bitsrc.io/introduction-to-promise-race-and-promise-any-with-real-life-examples-9d8d1b9f8ec9

作者:Mahdhi Rezvi

译文地址:https://segmentfault.com/a/1190000038475001

更多编程相关知识,请访问:编程入门!!

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!

Étiquettes associées:
source:segmentfault.com
Déclaration de ce site Web
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal