(Javascript)Promise.all、Promise.allSettled、Promise.race、Promise.resolve/reject、

Promise.all

  • Promise.all 接受一个 promise 数组作为参数,并返回一个新的 promise
  • 当所有给定的 promise 都被 settled 时,新的 promise 才会 resolve,并且其结果数组将成为新的 promise 的结果。
  • 结果数组中元素的顺序与其在源 promise 中的顺序相同。即使第一个 promise 花费了最长的时间才 resolve,但它仍是结果数组中的第一个。
    let promise = Promise.all([...promises...]);
//下面的Promise.all在3秒之后被settled,然后它的结果就是一个[1, 2, 3]数组
Promise.all([
  new Promise(resolve => setTimeout(() => resolve(1), 3000)), // 1
  new Promise(resolve => setTimeout(() => resolve(2), 2000)), // 2
  new Promise(resolve => setTimeout(() => resolve(3), 1000))  // 3
]).then(alert); // 1,2,3 当上面这些 promise 准备好时:每个 promise 都贡献了数组中的一个元素
  • 将一个任务数据数组映射(map)到一个 promise 数组,然后将其包装到 Promise.all。
let urls = [
  'https://api.github.com/users/iliakan',
  'https://api.github.com/users/remy',
  'https://api.github.com/users/jeresig'
];

// 将每个 url 映射(map)到 fetch 的 promise 中
/*
	map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
	map() 方法按照原始数组元素顺序依次处理元素。 
*/
let requests = urls.map(url => fetch(url));

// Promise.all 等待所有任务都 resolved
Promise.all(requests)
  .then(responses => responses.forEach(
    response => alert(`${response.url}: ${response.status}`)
  ));
  • 通过 GitHub 用户名来获取一个 GitHub 用户数组中用户的信息
let names = ['iliakan', 'remy', 'jeresig'];

let requests = names.map(name => fetch(`https://api.github.com/users/${name}`));

Promise.all(requests)
  .then(responses => {
    // 所有响应都被成功 resolved
    for(let response of responses) {
      alert(`${response.url}: ${response.status}`); // 对应每个 url 都显示 200
    }

    return responses;
  })
  // 将响应数组映射(map)到 response.json() 数组中以读取它们的内容
  .then(responses => Promise.all(responses.map(r => r.json())))
  // 所有 JSON 结果都被解析:"users" 是它们的数组
  .then(users => users.forEach(user => alert(user.name)));
  • 如果任意一个 promise 被 reject,由 Promise.all 返回的 promise 就会立即 reject,并且带有的就是这个 error。
Promise.all([
  new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)),
  new Promise((resolve, reject) => setTimeout(() => reject(new Error("Whoops!")), 2000)),
  new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000))
]).catch(alert); // Error: Whoops!

在这里插入图片描述


  • Promise.all(iterable) 允许在 iterable 中使用 non-promise 的“常规”值
  • Promise.all(...) 接受可迭代对象(iterable)的 promise(大多数情况下是数组)。但是,如果这些对象中的任意一个都不是 promise,那么它将被“按原样”传递给结果数组。
Promise.all([
  new Promise((resolve, reject) => {
    setTimeout(() => resolve(1), 1000)
  }),
  2,
  3
]).then(alert); // 1, 2, 3

Promise.allSettled

  • Promise.allSettled 等待所有的 promise 都被 settle,无论结果如何。结果数组具有:
  • {status:"fulfilled", value:result} 对于成功的响应,
  • {status:"rejected", reason:error} 对于 error。
let urls = [
  'https://api.github.com/users/iliakan',
  'https://api.github.com/users/remy',
  'https://no-such-url'
];

Promise.allSettled(urls.map(url => fetch(url)))
  /**
  results内容:
  *[
	  {status: 'fulfilled', value: ...response...},
	  {status: 'fulfilled', value: ...response...},
	  {status: 'rejected', reason: ...error object...}
   ]
  */
  .then(results => { // (*)
    results.forEach((result, num) => {
      if (result.status == "fulfilled") {
        alert(`${urls[num]}: ${result.value.status}`);
      }
      if (result.status == "rejected") {
        alert(`${urls[num]}: ${result.reason}`);
      }
    });
  });

Polyfill
  • 如果浏览器不支持Promise.allSettled,很容易进行 polyfill
if (!Promise.allSettled) {
  const rejectHandler = reason => ({ status: 'rejected', reason });

  const resolveHandler = value => ({ status: 'fulfilled', value });

  Promise.allSettled = function (promises) {
    const convertedPromises = promises.map(p => Promise.resolve(p).then(resolveHandler, rejectHandler));
    return Promise.all(convertedPromises);
  };
}
  • promises.map 获取输入值,并通过 p => Promise.resolve(p) 将输入值转换为 promise,然后向每一个 promise 都添加 .then 处理程序(handler
  • 这个处理程序(handler)将成功的结果 value 转换为 {status:'fulfilled', value},将 error reason 转换为 {status:'rejected', reason}。这正是 Promise.allSettled 的格式。

Promise.race

  • 与 Promise.all 类似,但只等待第一个 settled 的 promise 并获取其结果(或 error)。

let promise = Promise.race(iterable);

Promise.race([
  new Promise((resolve, reject) => setTimeout(() => resolve(1), 1000)),
  new Promise((resolve, reject) => setTimeout(() => reject(new Error("Whoops!")), 2000)),
  new Promise((resolve, reject) => setTimeout(() => resolve(3), 3000))
]).then(alert); // 1

Promise.resolve/reject

Promise.resolve
  • Promise.resolve(value) 用结果 value 创建一个 resolved 的 promise。
  • 当一个函数被期望返回一个 promise 时,这个方法用于兼容性。(译注:这里的兼容性是指,我们直接从缓存中获取了当前操作的结果 value,但是期望返回的是一个 promise,所以可以使用 Promise.resolve(value) 将 value “封装”进 promise,以满足期望返回一个 promise 的这个需求。)
    如同:
let promise = new Promise(resolve => resolve(value));
  • 例如,下面的 loadCached 函数获取(fetch)一个 URL 并记住其内容。以便将来对使用相同 URL 的调用,它能立即从缓存中获取先前的内容,但使用 Promise.resolve 创建了一个该内容的 promise,所以返回的值始终是一个 promise。
let cache = new Map();

function loadCached(url) {
  if (cache.has(url)) {
    return Promise.resolve(cache.get(url)); // (*)
  }

  return fetch(url)
    .then(response => response.text())
    .then(text => {
      cache.set(url,text);
      return text;
    });
}
  • 我们可以使用 loadCached(url).then(…),因为该函数保证了会返回一个 promise。我们就可以放心地在 loadCached 后面使用 .then。这就是 (*) 行中 Promise.resolve 的目的。
Promise.reject
  • Promise.reject(error) 用 error 创建一个 rejected 的 promise。
let promise = new Promise((resolve, reject) => reject(error));
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值