>웹 프론트엔드 >JS 튜토리얼 >Promise.race() 및 Promise.any() 사용 방법 이해

Promise.race() 및 Promise.any() 사용 방법 이해

青灯夜游
青灯夜游앞으로
2020-12-21 09:32:083838검색

Promise.race() 및 Promise.any() 사용 방법 이해

관련 추천: "javascript 비디오 튜토리얼"

JS는 1996년 출시 이후 꾸준히 개선되어 왔습니다. ECMAScript 버전이 많이 개선되어 최신 버전은 ES2020입니다. JS의 중요한 업데이트는 2015년에 ES6라는 이름으로 출시된 Promise입니다. ES2020。JS 的一个重要更新是Promise,在2015年,它以 ES6 的名义发布。

什么是 Promise ?

MDN 上对 Promise 的定义:Promise 对象用于表示一个异步操作的最终完成 (或失败)及其结果值。对于新手来说,这听起来可能有点太复杂了。

国外一位大什么对Promises的解释如下:“想象一下你是个孩子。 你老妈向你保证,她下周会给你买一部新手机。”

你要到下周才能知道你是否能获取那部手机。你老妈要么真的给你买了一个全新的手机,要么因为不开心就不给你买。

这个就是一个Promise。 一个Promise有三个状态。 分别是:

  1. Pending:你不知道你是否能得到那部手机
  2. Fulfilled:老妈高兴了,给你买了
  3. Rejected:老娘不开森了,不给你买了

这个是我目前听到,最快能理解 Promise 事例。

如果你还没有开始学习 Promise ,建议你这样做。

Promise包含几种非常有用的内置方法。 今天我们主要介绍这两种方法。

  • Promise.race()-与 ES6 一起发布
  • Promise.any() -仍处于第4阶段的提案中

Promise.race()

Promise.race()方法最初是在 ES6 中引入 Promise 时发布的,这个方法需要一个iterable作为参数。

Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise 就会解决或拒绝。

Promise.any()方法不同,Promise.race()方法主要关注 Promise 是否已解决,而不管其被解决还是被拒绝。

语法

Promise.race(iterable)

参数

iterable — 可迭代对象,类似 Array。 iterable 对象实现Symbol.iterator方法。

返回值

一个待定的 Promise 只要给定的迭代中的一个promise解决或拒绝,就采用第一个promise的值作为它的值,从而异步地解析或拒绝(一旦堆栈为空)。

注意

因为参数接受iterable,所以我们可以传递一些值,比如基本值,甚至数组中的对象。在这种情况下,race方法将返回传递的第一个非 promise 对象。这主要是因为方法的行为是在值可用时(当 promise 满足时)立即返回值。

此外,如果在iterable中传递了已经解决的Promise,则Promise.race()方法将解析为该值的第一个。 如果传递了一个空的Iterable,则race方法将永远处于待处理状态。

事例

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拒绝

真实用例

现在,你可能想知道,我们在实战中何时 Promise.race() ? 来看看。

在请求数据时,显示加载动画

使用加载动画开发中是非常常见。当数据响应时间较长时,如果没使用加载动画,看起来就像没有响应一样。但有时,响应太快了,我们需要加载动画时,增加一个非常小延迟时间,这样会让用户觉得我是在经常请求过来的。要实现这一点,只需使用Promise.race()方法,如下所示。

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

取消的 Promise

有些情况下,我们需要取消 Promise,这时也可以借助 Promise.race() 方法:

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

批处理请求,用于长时间执行

Chris Jensen 有一个有趣的race()方法用例。 他曾使用Promise.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 });

Promise.any()

Promise.any() 接收一个Promise可迭代对象,只要其中的一个 promise 成功,就返回那个已经成功的 promise 。如果可迭代对象中没有一个 promise 成功(即所有的 promises 都失败/拒绝),就返回一个失败的 promise 和AggregateError类型的实例,它是 Error 的一个子类,用于把单一的错误集合在一起。本质上,这个方法和Promise.all()

Promise란 무엇인가요?

MDN의 약속 정의: 약속 개체는 비동기 작업의 최종 완료(또는 실패)와 그 결과 값을 나타내는 데 사용됩니다. 초보자에게는 다소 복잡하게 들릴 수도 있습니다. 🎜🎜한 외국인 노인은 약속을 다음과 같이 설명했습니다. "당신이 어린아이라고 상상해 보세요. 어머니가 다음 주에 새 휴대폰을 사주겠다고 약속하십니다."🎜🎜You 당신은 알지 못할 것입니다. 다음 주까지 그 전화를 받을 수 있을지 말이에요. 당신의 엄마는 실제로 당신에게 새 휴대폰을 사줄 수도 있고, 아니면 마음에 들지 않아서 사주지 않을 수도 있습니다. 🎜🎜이것은 약속입니다. Promise에는 세 가지 상태가 있습니다. 🎜
  1. 보류 중: 해당 휴대전화를 받을 수 있는지 알 수 없음
  2. 이행됨: 엄마가 기뻐하며 사주셨음
  3. 거부됨: 엄마 죄송합니다. 사지 않겠습니다
🎜이것이 제가 지금까지 들어본 Promise 예제를 이해하는 가장 빠른 방법입니다. 🎜🎜아직 Promise를 배우기 시작하지 않으셨다면, 시작하시는 것을 추천드립니다. 🎜🎜Promise에는 몇 가지 매우 유용한 내장 메서드가 포함되어 있습니다. 오늘은 이 두 가지 방법을 주로 소개합니다. 🎜
  • Promise.race() - ES6으로 출시됨
  • Promise.any() - 아직 4단계 제안서에 있음

Promise.race()

🎜Promise.race() 메소드는 원래 Promise가 ES6에 도입되었을 때 출시되었습니다. 이 메소드에는 반복 가능을 매개변수로 사용합니다. 🎜🎜Promise.race(iterable) 메서드는 반복자의 promise가 해결되거나 거부되면 해결되거나 거부될 Promise를 반환합니다. 🎜🎜Promise.any() 메서드와 달리 Promise.race() 메서드는 주로 Promise의 해결 여부에 관계없이 Promise의 해결 여부에 중점을 둡니다. . 🎜

구문

Promise.any(iterable);

매개변수

🎜iterable — 배열과 유사한 반복 가능한 객체입니다. 반복 가능한 객체는 Symbol.iterator 메서드를 구현합니다. 🎜

반환 값

🎜 보류 중인 Promise는 주어진 반복에서 Promise가 해결되거나 거부될 때마다 첫 번째 Promise의 값을 값으로 사용하므로 참고🎜매개변수는 iterable을 허용하므로 기본 값이나 심지어 배열의 객체와 같은 일부 값을 전달할 수 있습니다. 이 경우 race 메소드는 전달된 첫 번째 비Promise 객체를 반환합니다. 이는 주로 메서드의 동작이 값을 사용할 수 있게 되자마자(프라미스가 충족될 때) 값을 반환하는 것이기 때문입니다. 🎜🎜 또한, 해결된 Promise가 iterable에 전달되면 Promise.race() 메서드는 해당 값의 첫 번째 값으로 해결됩니다. 빈 Iterable이 전달되면 race 메서드는 항상 보류됩니다. 🎜

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"

실제 사용 사례

🎜이제 Promise.race()를 실제로 언제 사용하는지 궁금하실 것입니다. 와서 한 번 보세요. 🎜🎜데이터 요청 시 로딩 애니메이션 표시🎜🎜개발 시 로딩 애니메이션을 사용하는 것은 매우 일반적입니다. 데이터 응답 시간이 긴 경우 로딩 애니메이션을 사용하지 않으면 응답이 없는 것처럼 보입니다. 하지만 때때로 응답이 너무 빠르면 애니메이션을 로드할 때 아주 작은 지연 시간을 추가해야 하므로 사용자가 자주 요청한다는 느낌을 받게 됩니다. 이를 달성하려면 아래와 같이 Promise.race() 메서드를 사용하면 됩니다. 🎜rrreee🎜취소된 약속 🎜🎜어떤 경우에는 약속을 취소해야 할 수도 있습니다. 이 경우 Promise.race() 메서드를 사용할 수도 있습니다. 🎜rrreee 🎜장기 실행에 대한 요청 일괄 처리🎜🎜Chris Jensen에는 race() 메서드에 대한 흥미로운 사용 사례가 있습니다. 그는 Promise.race() 메서드를 사용하여 장기 실행 요청을 일괄 처리했습니다. 이렇게 하면 병렬 요청 수를 고정된 상태로 유지할 수 있습니다. 🎜rrreee

Promise.any()

🎜Promise.any()Promise 반복 가능한 객체를 받습니다. 성공하면 성공적인 프라미스를 반환합니다. 반복 가능 항목의 promise 중 어느 것도 성공하지 않으면(즉, 모든 promise 실패/거부) 실패한 Promise와 AggregateError 유형이 반환됩니다. Error의 하위 클래스이며 단일 오류를 그룹화하는 데 사용되는 Error 인스턴스입니다. 기본적으로 이 메서드는 Promise.all()과 반대입니다. 🎜
注意! Promise.any() 方法依然是实验性的,尚未被所有的浏览器完全支持。它当前处于 TC39 第四阶段草案(Stage 4)

语法

Promise.any(iterable);

参数

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"

从上面代码注意到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

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

위 내용은 Promise.race() 및 Promise.any() 사용 방법 이해의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 segmentfault.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제