JS的ES6已经出来很久了,作为前端工程师如果对此还不熟悉有点说不过去。不过如果要问,Promise原生的api一共有哪几个?好像真的可以难倒一票人,包括我自己也忽略了其中一个不常用的API Promise.race。我们来瞧一下MDN对Promise的讲解: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

来看一下Promise的方法和prototype列表:

【1】Promise.prototype.catch 在Promise被reject的时候触发

【2】Promise.prototype.then 在Promise被resolve的时候触发

【3】Promise.prototype.finally 无论Promise是否resolve还是reject,都会触发。请注意,这个是一个比较新的特性,大部分浏览器并没有实现该特性。Promise.prototype.finally目前的浏览器兼容性列表如下:

该特性还在Stage 3阶段,等到在浏览器中大面积普及,估计要很久以后了。可以采用第三方库的实现,比如bluebird。

【4】Promise.resolve 直接返回一个已经resolve的Promise实例

【5】Promise.reject 直接返回一个已经reject的Promise实例

【6】Promise.all 传入一个Promise列表(常见的是由Promise组成的数组),只有当列表中所有的Promise都resolve时,该Promise才会resolve,只要有一个reject,则该Promise会reject。

【7】Promise.race 传入一个Promise列表,其中第一个resolve的Promise会使得该Promise.race 最终 resolve,如果第一个完成的Promise是reject的,那么Promise.race最终也reject(其实就是和跑的最快的那个Promise结果一样~)。

其实Promise的原生API也就这么几个,其中Promise.all和Promise.race是最容易被忽略的两个。我之前曾经不太熟悉Promise.race这个API导致实现一个需求卡住了很久。我们来通过一个小的练习熟悉该API的用法吧。

附上一道题目:

假设目前有1000个url下载链接,已经存储在数组url[1000]中(即url = ['http://example.com/video1.mp3', ...., 'http://example.com/video1000.mp3']),而且已经有一个函数function download,输入一个url链接,返回一个Promise,该Promise在链接下载完成的时候resolve,下载失败则reject。但是我们要求,任意时刻,同时下载的链接数量不可以超过10个。请写一段代码实现这个需求,要求尽可能快速地将该1000个链接下载完成。

思路:声明一个长度为10的,由Promise组成的数组,用Promise.race做汇总,只要检测到1个Promise resolve了,那就赶紧把那个Promise替换成一个新的再继续下载。

const TotalTaskCount = 1000; // 一共有1000个链接
const MaxConcurrency = 10; // 同时下载的链接数最大不超过10
const url = [...]; // 1000个下载链接组成的数组
const download = function (urlStr) {
// 返回Promise, 当下载完成的时候resolve
} Answer: let todoList = [];
let nextIndex = 0;
for (let j = 0; j < MaxConcurrency; j++) {
let task = download(url[nextIndex]).then(() => {return j}); // 注意这里resolve的值是任务在todoList的脚标,方便我们在Promise.race之后找到完成的任务脚标
todoList.push(task);
nextIndex++;
} const run = async function(todo) {
let index = await Promise.race(todo); // 这里index等于Promise.race第一个完成的任务的脚标
if (nextIndex < TotalTaskCount) {
todo[index] = download(url[nextIndex]).then(() => {return index;}); // 一旦有一个任务完成,马上把他替换成一个新的任务,继续下载
nextIndex++;
}
await run(todo);
} run(todoList);

最新文章

  1. Windows Server 2012 虚拟化实战:存储(一)
  2. js005-引用类型
  3. jQuery Mobile + HTML5
  4. CISA 信息系统审计知识点 [第一章. 信息系统审计过程 ]
  5. Atitit.木马&#160;病毒&#160;免杀&#160;技术&#160;360免杀&#160;杀毒软件免杀&#160;原理与原则&#160;attilax&#160;总结
  6. android AsyncTask 只能在线程池里单个运行的问题
  7. Margin and Padding in Windows Forms Controls
  8. Linux(Ubuntu)下MySQL的安装与配置
  9. 一种Android换肤机制的实现
  10. Python学习笔记 (2) :字符串输出、操作、格式化和日期、时间格式化
  11. EXTJS4两个ComboBox的数据源联动,解决遇到第二个ComboBox第二次以后显示忙的状态问题
  12. sdkman安装
  13. 如何通过 WebP 自适应方案减少图片资源大小
  14. VR全景加盟-全景智慧城市携万千创业者决战BAT
  15. (转)java之Spring(IOC)注解装配Bean详解
  16. LINUX学习 - 磁盘分区 + 开机自动挂载 + 性能测试
  17. php中parse_url函数解析
  18. mysql root密码忘记重置及相关注意事项
  19. There is no getter for property named &#39;notice&#39; in &#39;class com.game.domain.Notices&#39;
  20. SVM引入拉格朗日乘子[转载]

热门文章

  1. Liunx初学指令
  2. riot.js教程【五】标签嵌套、命名元素、事件、标签条件
  3. powerdesigner 不能自动生成注释的解决方法
  4. 2981:大整数加法-poj
  5. Python基础学习-&#39;module&#39; object has no attribute &#39;urlopen&#39;解决方法
  6. javascript权威指南pdf
  7. Django框架中的视图和模板
  8. wkwebview加载本地html的要点
  9. Tomcat 日志分割
  10. poj 3431 Expedition 优先队列