🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[链接111111111111111111](https://segmentfault.com/a/1190000018116310) [链接](https://juejin.im/post/5cd113f7f265da03b57b6dd6) ### Promise优缺点 * 优点: 解决回调地狱, 对异步任务写法更标准化与简洁化 * 缺点: 首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消; 其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部; 第三,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成). <div id="div13"><h3> <font color=red /> 13,promise, promise.all, promise.race <h3></div> 回调函数里面回调另一个函数 - 13-1 **promise** Promise状态,只有pending,fulfilled,rejected 3种状态,而且不可逆,从创建实例时的pending,调用成功resolve就变成fulfilled,失败则变为rejected, 三种状态: Pending状态(进行中);Fulfilled状态(已成功);Rejected状态(已失败) ```javascript var promise=new Promsie(function(resolve,rejec){ if(/*异步执行成功*/){ resolve(value); }else{ reject(error); } }) .then(function(){ //回调执行成功之后的操作 },function(){ //回调执行失败之后的操作,可以没有 }); ``` - **promise 链式操作** ```javascript new AjPromise((resolve, reject) => { setTimeout(() => { resolve(2); }, 2000); }) .then(res => { console.log(res); return res + 1; }) .then(res => { console.log(res); }); // delay 2s.. 2 3 ``` - **js 实现 promise** **1,Promise 构造器函数,传入一个函数,该函数立即执行,并且有resolve和reject两个参数,resolve被调用时Promise状态变为fulfilled; 2,实现then方法,传入一个函数,该该数在Promise被fulfilled时执行** ```javascript function PromiseM(){ this.status='pending'; this.msg=''; var process=arguments[0]; var that=this; process(function(){ that.status='resolve'; that.msg=arguments[0]; },function(){ that.status='reject'; that.msg=arguments[0]; }); return this; } PromiseM.prototype.then=function(){ if(this.status=='resolve'){ arguments[0](this.msg); } if(this.status=='reject'&&arguments[1]){ arguments[1](this.msg); } } //测试用例 var mm=new PromiseM(function(resolve,reject){ resolve('123');//123其实就是第二个arguments[0] });//上面的第一个arguments[0] mm.then(function(success){ console.log(success);//该success其实就是上面的this.msg console.log("ok!"); },function(){ console.log('fail!'); }); //123 //ok ``` - 13-2 **promise.all** promise只有2个状态,成功和失败,怎么让一个函数无论成功还是失败都能被调用?--promise.all Promise.all可以将多个Promise实例包装成一个新的Promise实例。同时,成功和失败的返回值是不同的, 成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值。 ```javascript let wake = (time) => { return new Promise((resolve, reject) => { setTimeout(() => { resolve(`${time / 1000}秒后醒来`) }, time) }) } let p1 = wake(3000) let p2 = wake(2000) Promise.all([p1, p2]).then((result) => { console.log(result) // [ '3秒后醒来', '2秒后醒来' ] }).catch((error) => { console.log(error) }) ``` - **promise.all 实现** ```javascript Promise.all = arr => { let aResult = []; //用于存放每次执行后返回结果 return new _Promise(function (resolve, reject) { let i = 0; next(); // 开始逐次执行数组中的函数(重要) function next() { arr[i].then(function (res) { aResult.push(res); // 存储每次得到的结果 i++; if (i == arr.length) { // 如果函数数组中的函数都执行完,便resolve resolve(aResult); } else { next(); } }) } }) }; ``` - 13-3 **Promise.race** Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果, 不管结果本身是成功状态还是失败状态。只保留取第一个执行完成的异步操作的结果, 其他的方法仍在执行,不过执行结果会被抛弃。 ```javascript let p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve('success') },1000) }) let p2 = new Promise((resolve, reject) => { setTimeout(() => { reject('failed') }, 500) }) Promise.race([p1, p2]).then((result) => { console.log(result) }).catch((error) => { console.log(error) // 打开的是 'failed' }) ``` `Promise.race()`方法接受一个包含 Promise 对象或普通值的数组(或其它可迭代对象)作为参数,并返回一个 Promise。一旦其中之一的 Promise 对象 resolve 以后,立即把 resolve 的值作为`Promise.race()`resolve 的结果。如果其中之一的对象 reject,`Promise.race`也会立即 reject。 在实际应用中,如果可以从几个接口获取相同的数据,哪个接口数据先到就先用哪个,就可以使用`Promise.race()`,所需时间等于其中最快的那个接口。下面是代码: ~~~ const race = function (iterable) { return new Promise(function (resolve, reject) { for (const i in iterable) { const v = iterable[i] if (typeof v === 'object' && typeof v.then === 'function') { v.then(resolve, reject) } else { resolve(v) } } }) } const p1 = new Promise(function (resolve) { setTimeout(resolve, 200, 1) }) const p2 = new Promise(function (resolve) { setTimeout(resolve, 100, 2) }) race([p1, p2]).then(function (res) { console.log(res) }) // 2 ~~~ ## Promise捕获异常这里有两种方式 * * * **第一种单独对 .then() 中指定异常处理函数(第一种一般用在,希望捕获异常然后不影响接下里Promise的执行)** ![](https://img.kancloud.cn/28/99/2899eaafab15154e135dea7ab72f15c4_388x314.png) 我们只需要在 .then() 中添加两个function就好了,第二个是用来处理失败的情况。 第二种使用.catch来实现全部捕获(第二种一般用在,当一个Promise发生了异常,剩下的Promise都不在执行) ![](https://img.kancloud.cn/f3/44/f3443ba5d60d17e610def2155ce80a20_471x325.png)