promise的状态以及api介绍_面试题,实现一个Promise.first()

// (1.)最短时间内找出(2.)响应速度最快且(3.)成功的接口。
// 实现 findFatest 函数。

const urls = [
    'https://www.toutiao.com/a',
    'https://www.toutiao.com/b',
    'https://www.toutiao.com/bb',
    'https://www.toutiao.com/d',
    'https://www.toutiao.com/e',
]
findFatest(urls).then(url => console.log(url)
  • 最短时间找出相当于限制 ->只能用fetch(),它返回一个promise,防止答题者用setTimeout遍历出ajax 请求包裹上promise来(用回调即一个异步执行完成后在执行下一个请求,这样很不错,但是问题又来了,延迟延迟延迟,请求越多最后的那个请求延迟就会越严重)
  • 同时发送的话相当于限制 -> 用Promise.all() 或 Promise.race()
  • 响应速度最快且(3.)成功的接口 -> 最快或者说第一个就用Promise.race()了, 但是Promise.race()在第一个拒绝时候也返回,所以不符合。
  • 那么问题来考的是啥呢? 直到我翻开了《你不知道的javascript 中卷》的p217页 其实是要实现一个Promise.first([...])

这算是实现一个Promise.all() 和Promise.race()的变体:

要求: 只要第一个Promise完成(注意必须是完成,而非拒绝,这也是这题Promise.race()不符合的原因),它就会忽略后续的任何拒绝和完成

ac2ddfefcbdd345d832c5ab270f6a07c.png
总体来看 , first 类似race,但是只要有一个promise决议为完成(忽略前边被拒绝的promise),就忽略后边的promise

我们来把上面的代码补全(加上如果promise都被拒绝了,就在主promise上调用reject()的逻辑)

ae8a9560ee5eb64df8d7d08e0bb85213.png

测试一下,下面是测试用例

const promisesForFirstTest1= [ // 模拟开始问题的fetch请求urls返回值
    Promise.reject('1'),
    Promise.resolve('2'),
    Promise.reject('3'),
    Promise.resolve('4'),
  ]
  Promise.first(promisesForFirstTest1).then(res => {
    debugger // 执行到此,res 为 '2'
  }, res => {
    debugger
  })

  const promisesForFirstTest2= [
    Promise.reject('1'),
    Promise.resolve('2'),
    Promise.reject('3'),
    Promise.resolve('4'),
  ]
  Promise.first(promisesForFirstTest2).then(res => {
    debugger 
  }, res => {
    debugger // 执行到此
  })

828e37efa1536c0d86141bb17dcf08ea.png

由此我们还会遇到其他的扩展需求,比如:

  • Promise.none([...]): 这个模式类似于Promise.all([...]),不过和 Promise.all 相反,当所有的promise被拒绝之后,none方法执行完成的决议,如果存在一个promise执行完成的决议,none方法则执行拒绝
  • Promise.any([...]): 忽略被拒绝的promise,只需要有一个完成的promise,any方法就执行完成操作,如果全部的promise都被拒绝,any方法执行拒绝操作

并发迭代

基础知识讲解(复习一遍)

fetch

98035e6dd323a8f6a6b742bb954eec55.png

179cd7a9d8480b872c5b1fff0c486a7a.png

get请求

一个基本的 fetch请求设置起来很简单,这里发起一个get请求。看看下面的代码

(用myjson造个接口)

// 测试接口
fetch('https://api.myjson.com/bins/iyzpa')
  .then(function(response) {
    return response.json();
  })
  .then(function(myJson) {
    console.log(myJson);
  });

215dab5c44a9ba6c754cfd9d7f8795f8.png

调用fetch函数,传入接口url,然后返回一个promise(response),为了获取JSON的内容,我们需要使用json()方法,这个方法返回的也是一个promise。

post请求

发起一个post请求,我们用JSONPlaceholder造个

fetch('https://jsonplaceholder.typicode.com/posts', {
    method: 'POST',
    body: JSON.stringify({
        name: "白鲸鱼",
        age: 10000
    }),
    headers: {
      "Content-type": "application/json; charset=UTF-8"
    }
  })
  .then(response => response.json())
  .then(json => console.log(json))

0726bb999594bea3a0e282e8c82e77fc.png

还可以配合serve worker使用 ---> 使用Service Worker和离线缓存Cache

Promise.all()

c7ac2c4e46eafb6b62294486d27a65fb.png
类方法,多个 Promise 任务同时执行。
如果全部成功执行,则以数组的方式返回所有 Promise 任务的执行结果。 如果有一个 Promise 任务 rejected,则只返回 rejected 任务的结果。
Promise.all方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。
const p = Promise.all([p1, p2, p3]);

p1,p2,p3组成一个数组,都是promise实例。

p的状态由p1、p2、p3决定,分成两种情况:
(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

754221d9fbbcc1a69fca7f8ca98e3365.png

上面代码中,Promise.all()内的参数是 2个 会返回Promise的接口请求,只有这 2 个请求的状态都变成fulfilled,或者其中有一个变为rejected,才会调用Promise.all方法后面的回调函数。

7644003241df4709ad3211d0e27a712f.png

476088419be124305bf33376a493e67b.png

1、 如果参数中包含非promise值,这些值将被忽略,但仍然会被放在返回数组中(如果promise完成的话)

下面的例子中演示了Promise.all 的异步性(如果传入的可迭代对象是空的,就是同步):

严格来说.传给 Promise.all([...])的数组的元素可以是Promise, thenable,甚至是立即值。
就本质而言 , 列表中的每个值都会通过Promise.resolve(...)过滤, 以确保等待的是一个真正的Promise, 所以立即值会被规范化为这个值构建的Promise。
如果数组是空的,主Promise就会立即完成(另外, Promise.all 当且仅当传入的可迭代对象为空时为同步)

ca756080bb011aef6a00851ad13b0481.png

3f5b75a984400286ea70ab516bd96e84.png

Promise.race()

Promise.race方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。

Promse.race就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。

const p = Promise.race([p1, p2, p3]);

5a21d1c042e2e4d48eee63760e91e589.png
The Promise.race(iterable) method returns a promise that resolves or rejects as soon as one of the promises in the iterable resolves or rejects, with the value or reason from that promise.
意思是Promise.race会返回参数中第一个执行完毕的promise的结果(无论是已完成还是已拒绝)

c0e7461c9ff58b942da75fc64da493b4.png

Promise.race([...])也接受单个数组参数,这个数组由一个或多个Promise, thenable或立即值组成

立即值之间的竞争在实践中没有多大意义,因为显然列表中的第一个会获胜,就像赛跑中有个选手是从终点开始比赛一样。

201f119e8c13e1925261865826c43711.png
注意1: 永远要记住为每个promise关联一个拒绝/错误处理函数(catch)

05a17f22ba039b55794396b3f76fc8b5.png
注2: 若向Promise.all([...])传入空数组,它会立即完成,但Promise.race([...])会挂住,且永远不会决议

参考

Promise.race 结果(深入理解ES6书籍有误)​www.jianshu.com Promise.race()​developer.mozilla.org
9bf579c198e308707a076418620f9bc4.png
Promise.all()​developer.mozilla.org
9bf579c198e308707a076418620f9bc4.png

《你不知道的js 中卷》

dojo/promise/first - The Dojo Toolkit - Reference Guide​dojotoolkit.org 人类身份验证 - SegmentFault​segmentfault.com 给ES6 Promise 扩展always方法​www.jianshu.com
b92e01ad27c232713030dffa2100da27.png
https://github.com/juneidysoo/promise-first/blob/master/index.js​github.com Promise.prototype.catch()​developer.mozilla.org
9bf579c198e308707a076418620f9bc4.png
frontarm/async-javascript-cheatsheet​github.com
eea9f625c9a7a0a676a534c100c00003.png
总结一下ES6/ES7中promise、generator和async/await中的异常捕获方法 · Issue #16 · forthealllight/blog​github.com
623e4eccf1b0530d5829510849b553cd.png

http://weixin.qq.com/r/hElmfgPEdF4LrUcd9xyW (二维码自动识别)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值