// (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](https://i-blog.csdnimg.cn/blog_migrate/d5a5c10c0b3da1337b3956684e18c621.jpeg)
总体来看 , first 类似race,但是只要有一个promise决议为完成(忽略前边被拒绝的promise),就忽略后边的promise
我们来把上面的代码补全(加上如果promise都被拒绝了,就在主promise上调用reject()的逻辑)
![ae8a9560ee5eb64df8d7d08e0bb85213.png](https://i-blog.csdnimg.cn/blog_migrate/f8ad29f91a8fb18799cff38c09ab9344.jpeg)
测试一下,下面是测试用例
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](https://i-blog.csdnimg.cn/blog_migrate/6bad4530f035ed797af59cbe72962479.jpeg)
由此我们还会遇到其他的扩展需求,比如:
- Promise.none([...]): 这个模式类似于Promise.all([...]),不过和 Promise.all 相反,当所有的promise被拒绝之后,none方法执行完成的决议,如果存在一个promise执行完成的决议,none方法则执行拒绝
- Promise.any([...]): 忽略被拒绝的promise,只需要有一个完成的promise,any方法就执行完成操作,如果全部的promise都被拒绝,any方法执行拒绝操作
并发迭代
基础知识讲解(复习一遍)
fetch
![98035e6dd323a8f6a6b742bb954eec55.png](https://i-blog.csdnimg.cn/blog_migrate/79862bc502f9665041ebde3983e7e8c2.jpeg)
![179cd7a9d8480b872c5b1fff0c486a7a.png](https://i-blog.csdnimg.cn/blog_migrate/d352b7f0c0e3a3dc5d327ef44a53e6b2.jpeg)
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](https://i-blog.csdnimg.cn/blog_migrate/2c587a1d9a11383dcc61d27b57213516.jpeg)
调用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](https://i-blog.csdnimg.cn/blog_migrate/594e82b7393b39d15d63ae5e4965fd84.jpeg)
还可以配合serve worker使用 ---> 使用Service Worker和离线缓存Cache
Promise.all()
![c7ac2c4e46eafb6b62294486d27a65fb.png](https://i-blog.csdnimg.cn/blog_migrate/8565bb22eec3cc2a0d42620d4d412d5b.jpeg)
类方法,多个 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](https://i-blog.csdnimg.cn/blog_migrate/514671a3c3e7c9eb687d14a8e8a9da14.jpeg)
上面代码中,Promise.all()内的参数是 2个 会返回Promise的接口请求,只有这 2 个请求的状态都变成fulfilled,或者其中有一个变为rejected,才会调用Promise.all方法后面的回调函数。
![7644003241df4709ad3211d0e27a712f.png](https://i-blog.csdnimg.cn/blog_migrate/b050e41c1a36b8b510790c14fdf9955e.jpeg)
![476088419be124305bf33376a493e67b.png](https://i-blog.csdnimg.cn/blog_migrate/3c0e1b203ed942fbab26d6e921341897.jpeg)
1、 如果参数中包含非promise
值,这些值将被忽略,但仍然会被放在返回数组中(如果promise
完成的话)
下面的例子中演示了Promise.all
的异步性(如果传入的可迭代对象是空的,就是同步):
严格来说.传给 Promise.all([...])的数组的元素可以是Promise, thenable,甚至是立即值。
就本质而言 , 列表中的每个值都会通过Promise.resolve(...)过滤, 以确保等待的是一个真正的Promise, 所以立即值会被规范化为这个值构建的Promise。
如果数组是空的,主Promise就会立即完成(另外,Promise.all
当且仅当传入的可迭代对象为空时为同步)
![ca756080bb011aef6a00851ad13b0481.png](https://i-blog.csdnimg.cn/blog_migrate/78c3f683044c88156ae49367913de236.jpeg)
![3f5b75a984400286ea70ab516bd96e84.png](https://i-blog.csdnimg.cn/blog_migrate/c6651f62337e86a5d9a0132e931fea5d.jpeg)
Promise.race()
Promise.race方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。
Promse.race就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。
const p = Promise.race([p1, p2, p3]);
![5a21d1c042e2e4d48eee63760e91e589.png](https://i-blog.csdnimg.cn/blog_migrate/243dc740b9e7390868d8c6628fb81b80.jpeg)
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](https://i-blog.csdnimg.cn/blog_migrate/520accfb1bb3717c1751e206f8e80a64.jpeg)
Promise.race([...])也接受单个数组参数,这个数组由一个或多个Promise, thenable或立即值组成
立即值之间的竞争在实践中没有多大意义,因为显然列表中的第一个会获胜,就像赛跑中有个选手是从终点开始比赛一样。
![201f119e8c13e1925261865826c43711.png](https://i-blog.csdnimg.cn/blog_migrate/5df59de7292deba48d044d5134025aca.jpeg)
注意1: 永远要记住为每个promise关联一个拒绝/错误处理函数(catch)
![05a17f22ba039b55794396b3f76fc8b5.png](https://i-blog.csdnimg.cn/blog_migrate/33c138a3906f2b6f9c2a9279c67e3b1e.jpeg)
注2: 若向Promise.all([...])传入空数组,它会立即完成,但Promise.race([...])会挂住,且永远不会决议
参考
Promise.race 结果(深入理解ES6书籍有误)www.jianshu.com Promise.race()developer.mozilla.org![9bf579c198e308707a076418620f9bc4.png](https://i-blog.csdnimg.cn/blog_migrate/afee5ba14a1cd34ff0b40154ab89b5d8.jpeg)
![9bf579c198e308707a076418620f9bc4.png](https://i-blog.csdnimg.cn/blog_migrate/afee5ba14a1cd34ff0b40154ab89b5d8.jpeg)
《你不知道的js 中卷》
dojo/promise/first - The Dojo Toolkit - Reference Guidedojotoolkit.org 人类身份验证 - SegmentFaultsegmentfault.com 给ES6 Promise 扩展always方法www.jianshu.com![b92e01ad27c232713030dffa2100da27.png](https://i-blog.csdnimg.cn/blog_migrate/f02f5da00bdb162ed5cc8503df753fa9.jpeg)
![9bf579c198e308707a076418620f9bc4.png](https://i-blog.csdnimg.cn/blog_migrate/afee5ba14a1cd34ff0b40154ab89b5d8.jpeg)
![eea9f625c9a7a0a676a534c100c00003.png](https://i-blog.csdnimg.cn/blog_migrate/da7cf8b01408f602486731b54d6d8082.png)
![623e4eccf1b0530d5829510849b553cd.png](https://i-blog.csdnimg.cn/blog_migrate/7fc2a70287b030b68525306d19b14be0.jpeg)
http://weixin.qq.com/r/hElmfgPEdF4LrUcd9xyW (二维码自动识别)