什么是Promise
Promise 是一个构造函数,自身具有all, allSettled, resolve,reject, race 等方法,原型上有then, catch, finally等方法(因此我们通过 Promise 构造函数实例化的 实例仍然具有这些方法)
console.log(Promise)-------------------------------------ƒ Promise()> all: ƒ all()> allSettled: ƒ allSettled()> any: ƒ any()> arguments: (...)> caller: (...)> length: 1> name: "Promise"> prototype: Promisecatch: ƒ catch()constructor: ƒ Promise()finally: ƒ finally()then: ƒ then()Symbol(Symbol.toStringTag): "Promise"__proto__: Object> race: ƒ race()> reject: ƒ reject()> resolve: ƒ resolve()> Symbol(Symbol.species): (...)> Symbol(allSettled): ƒ (d)> get Symbol(Symbol.species): ƒ [Symbol.species]()> __proto__: ƒ ()> [[Scopes]]: Scopes[0]
Promise基本用法
then & catch
function getNumber(){var p = new Promise(function(resolve, reject){//做一些异步操作setTimeout(function(){var num = Math.ceil(Math.random()*10); //生成1-10的随机数if(num<=5){resolve(num);}else{reject('数字太大了');}}, 2000);});return p;}// 写法一getNumber() // 函数执行返回一个Promise对象.then(function(data){ // resolve 函数, 异步任务执行成功的回调console.log('resolved');console.log(data);},function(reason, data){ // reject 函数, 异步任务执行失败的回调console.log('rejected');console.log(reason);});// 写法二getNumber().then(function(data){ // resolve 函数, 异步任务执行成功的回调console.log('resolved');console.log(data);}).catch(function(data){ // reject 函数, 异步任务执行失败的回调console.log('rejected');console.log(reason);})
all的用法
Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调
有了all,你就可以并行执行多个异步操作,并且在一个回调中处理所有的返回数据,一些游戏类的素材比较多的应用,打开网页时,预先加载需要用到的各种资源如图片、flash以及各种静态文件。所有的都加载完后,我们再进行页面的初始化。
function runAsync1(){let p1 = new Promise(function(resolve, reject){// 执行一些异步任务setTimeOut(function(){console.log('异步任务1执行完成');resolve('随便什么数据1')}, 2000)})return p1;}function runAsync2(){let p1 = new Promise(function(resolve, reject){// 执行一些异步任务setTimeOut(function(){console.log('异步任务2执行完成');resolve('随便什么数据2')}, 2000)})return p2;}function runAsync3(){let p1 = new Promise(function(resolve, reject){// 执行一些异步任务setTimeOut(function(){console.log('异步任务3执行完成');resolve('随便什么数据3')}, 2000)})return p3;}// 接受三个异步执行的函数,三个异步操作的并行执行的,等到它们都执行完后才会进到then里面Promise.all([runAsync1(), runAsync2(), runAsync3()]).then((result)=>{console.log(result);// 异步任务1执行完成// 异步任务2执行完成// 异步任务3执行完成// ["随便什么数据1", "随便什么数据2", "随便什么数据3"]})
race的用法
谁跑的快,以谁为准执行回调
多个异步任务同时执行,如果有一个任务执行完成,执行回调函数,后续的任务正常执行,不在打印回调结果
function runAsync1(){let p1 = new Promise(function(resolve, reject){// 执行一些异步任务setTimeOut(function(){console.log('异步任务1执行完成');resolve('随便什么数据1')}, 2000)})return p1;}function runAsync2(){let p1 = new Promise(function(resolve, reject){// 执行一些异步任务setTimeOut(function(){console.log('异步任务2执行完成');resolve('随便什么数据2')}, 2000)})return p2;}function runAsync3(){let p1 = new Promise(function(resolve, reject){// 执行一些异步任务setTimeOut(function(){console.log('异步任务3执行完成');resolve('随便什么数据3')}, 2000)})return p3;}Promise.race([runAsync1(), runAsync2(),runAsync3()]).then((result)=>{console.log(result);// 异步任务1执行完成// 随便什么数据1// 异步任务2执行完成// 异步任务3执行完成})
使用场景
可以用race给某个异步请求设置超时时间,并且在超时后执行相应的操作
请求图片任务、超时5s任务 两个任务 执行Promise.race() 如果超过5s图片任务还没有请求图片,则执行超时任务提升超时
function getImg(){let p = new Promise(function(resolve, reject){let img = new Image();img.onload = function(){resolve(img)}img.src = 'https://cdn.nlark.com/yuque/0/2020/png/152077/1606703278597-fdcaa8e1-3394-463a-bac2-c2dcfa3df160.png';})return p;}function timeout(){let p = new Promise(function(resolve, reject){setTimeout(function(){reject('图片超时了')}, 5000)})return p;}Promise.race([getImg(), timeout()]).then(function(data){console.log(data);}).catch(function(error){console.log(error);})
参考
- 大白话讲解Promise(一)
 - 大白话讲解Promise(二)理解Promise规范
 - Promise A+ 规范
 - JavaScript Promise迷你书(中文版)
 - ES6 Promise
 - 手写Promise https://juejin.cn/post/6844903843507994632
 
