Promise是什么? Promise是JS异步编程中的重要概念,异步抽象处理对象,是目前比较流行Javascript异步编程解决方案之一。这句话说的很明白了,Promise是一种用于解决异步问题的思路、方案或者对象方式。
Promise基本Api
Promise.resolve()
Promise.reject()
Promise.prototype.then()
Promise.prototype.catch()
Promise.prototype.finally()
Promise.all() // 所有的完成
Promise.race() // 竞速,完成一个即可
Promise用法
首先,Promise是一个对象,因此,我们使用new的方式新建一个。
然后给它传一个函数作为参数,这个函数呢也有两个参数,一个叫resolve(决定),一个叫reject(拒绝),这两个参数也是函数。
紧接着,我们使用then来调用这个Promise。
参考代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 new Promise (function (resolve, reject ) { setTimeout (()=> { let num = Math .ceil (Math .random () * 10 ) if (num > 2 ) { resolve (num) } else { reject (num) } },2000 ); }).then ((res )=> { console .log (res); },(err )=> { console .log (err); })
Promise原理 在Promise的内部,有一个状态管理器的存在,有三种状态:pending、fulfilled、rejected。
promise 对象初始化状态为 pending
当调用resolve(成功),会由pending => fulfilled
当调用reject(失败),会由pending => rejected
promsie状态 只能由 pending => fulfilled/rejected, 一旦修改就不能再变(记住,一定要记住); 当状态为fulfilled(rejected反之)时,then的成功回调函数会被调用,并接受上面传来的num,进而进行操作;promise.then方法每次调用,都返回一个新的promise对象 所以可以链式写法(无论resolve还是reject都是这样)。
Promise方法 then then方法用于注册当状态变为fulfilled或者reject时的回调函数:
catch
catch能捕获reject(err)中返回的错误。
catch还能捕获链式调用then(()=>{}, ()=>{})中里面代码异常。
1 2 3 4 5 6 7 8 9 10 11 12 13 const fn = new Promise (function (resolve, reject ) { let num = Math .ceil (Math .random () * 10 ) if (num > 10 ) { resolve (num) } else { reject (num) } }) fn.then ((res )=> { console .log (res1) }).catch ((err )=> { console .log (`err==>${err} ` ) })
resolve、reject Promise.resolve 返回一个fulfilled状态的promise对象,Promise.reject 返回一个rejected状态的promise对象
1 2 3 4 5 6 7 8 9 Promise.resolve('hello').then(function(value){ console.log(value); }); Promise.resolve('hello'); // 相当于 const promise = new Promise(resolve => { resolve('hello'); });
all
大概就是作为参数的几个promise对象一旦有一个的状态为rejected,则all的返回值就是rejected。
1 2 3 4 5 6 7 8 9 10 var p1 = Promise.resolve(1), p2 = Promise.reject(2), p3 = Promise.resolve(3); Promise.all([p1, p2, p3]).then((res)=>{ //then方法不会被执行 console.log(results); }).catch((err)=>{ //catch方法将会被执行,输出结果为:2 console.log(err); });
当这几个作为参数的函数的返回状态为fulfilled时,至于输出的时间就要看谁跑的慢了:
race 介绍: promise.race()方法也可以处理一个promise实例数组但它和promise.all()不同,从字面意思上理解就是竞速,那么理解起来上就简单多了,也就是说在数组中的元素实例那个率先改变状态,就向下传递谁的状态和异步结果。但是,其余的还是会继续进行的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 let p1 = new Promise((resolve)=>{ setTimeout(()=>{ console.log('1s') //1s后输出 resolve(1) },1000) }) let p10 = new Promise((resolve)=>{ setTimeout(()=>{ console.log('10s') //10s后输出 resolve(10) //不传递 },10000) }) let p5 = new Promise((resolve)=>{ setTimeout(()=>{ console.log('5s') //5s后输出 resolve(5) //不传递 },5000) }) Promise.race([p1, p10, p5]).then((res)=>{ console.log(res); // 最后输出 }) //输入结果 1s 1 5s 10s
使用场景: 超时处理 图片超时
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 //请求某个图片资源 let requestImg = new Promise(function(resolve, reject){ var img = new Image(); img.onload = function(){ resolve(img); } }); //延时函数,用于给请求计时 let timeOut = new Promise(function(resolve, reject){ setTimeout(function(){ reject('图片请求超时'); }, 5000); }); Promise.race([requestImg, timeout]).then((res)=>{ console.log(res); }).catch((err)=>{ console.log(err); });
Promise面试题
1,Promise状态一旦改变,无法在发生变更
1 2 3 4 5 6 7 8 9 10 11 12 const promise = new Promise((resolve, reject) => { setTimeout(() => { resolve('success') reject('error') }, 1000) }) promise.then((res)=>{ console.log(res) },(err)=>{ console.log(err) }) //输出结果:success
2,Promise的then方法的参数期望是函数,传入非函数则会发生值穿透。
1 2 3 4 5 Promise.resolve(1) .then(2) .then(Promise.resolve(3)) .then(console.log) //输出结果:1
3,实现一个简单的Promise
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 function Promise(fn){ var status = 'pending' function successNotify(){ status = 'fulfilled'//状态变为fulfilled toDoThen.apply(undefined, arguments)//执行回调 } function failNotify(){ status = 'rejected'//状态变为rejected toDoThen.apply(undefined, arguments)//执行回调 } function toDoThen(){ setTimeout(()=>{ // 保证回调是异步执行的 if(status === 'fulfilled'){ for(let i =0; i< successArray.length;i ++) { successArray[i].apply(undefined, arguments)//执行then里面的回掉函数 } }else if(status === 'rejected'){ for(let i =0; i< failArray.length;i ++) { failArray[i].apply(undefined, arguments)//执行then里面的回掉函数 } } }) } var successArray = [] var failArray = [] fn.call(undefined, successNotify, failNotify) return { then: function(successFn, failFn){ successArray.push(successFn) failArray.push(failFn) return undefined // 此处应该返回一个Promise } } }
解题思路:Promise中的resolve和reject用于改变Promise的状态和传参,then中的参数必须是作为回调执行的函数。因此,当Promise改变状态之后会调用回调函数,根据状态的不同选择需要执行的回调函数。
文章来源于掘金