ES6--浅析Promise内部结构 (4)

2、catch的实现

// 原生Promise的catch使用 Promise.reject('hello swr').catch((e)=>{ console.log(e) // hello swr }) // 上面这段代码相当于下面这段代码 Promise.reject('hello swr').then(null,(e)=>{ // then里直接走了失败的回调 console.log(e) // hello swr }) // 内部实现 Promise.prototype.catch = function(onRejected){ return this.then(null,onRejected) // 相当于then里的成功回调只传个null }

 

3、promise.all的实现同时执行多个异步,并且返回一个新的promise,成功的值是一个数组,该数组的成员的顺序是传参给promise.all的顺序

// 原生Promise.all的使用 // 假设1.txt内容为hello 2.txt内容为swr let fs = require('fs') function read(filePath,encoding){ return new Promise((resolve,reject)=>{ fs.readFile(filePath,encoding,(err,data)=>{ if(err) reject(err) resolve(data) }) }) } Promise.all([read('./1.txt','utf8'),read('./2.txt','utf8')]).then((data)=>{ console.log(data) // 全部读取成功后返回 ['hello','swr'] // 需要注意的是,当其中某个失败的话,则会走失败的回调函数 })

promise.all内部实现

Promise.all = function(promises){ // promises 是一个数组 return new Promise((resolve,reject)=>{ let arr = [] let i = 0 function processData(index,data){ arr[index] = data // 5.我们能用arr.length === promises.length来判断请求是否全部完成吗? // 答案是不行的,假设arr[2] = 'hello swr' // 那么打印这个arr,将是[empty × 2, "hello swr"], // 此时数组长度也是为3,而数组arr[0] arr[1]则为空 // 那么换成以下的办法 if(++i === promises.length){ // 6.利用i自增来判断是否都成功执行 resolve(arr) // 此时arr 为['hello','swr'] } } for(let i = 0;i < promises.length;i++){ // 1.在此处遍历执行 promises[i].then((data)=>{ // 2.data是成功后返回的结果 processData(i,data) // 4.因为Promise.all最终返回的是一个数组成员按照顺序排序的数组 // 而且异步执行,返回并不一定按照顺序 // 所以需要传当前的i },reject) // 3.如果其中有一个失败的话,则调用reject } }) }

 

4、promise.race方法实现,同时执行多个异步,然后那个快,就用那个的结果,race是赛跑

// 原生Promise.race的使用 // 一个成功就走成功的回调,一个失败就走失败的回调 Promise.race([read('./1.txt','utf8'),read('./2.txt','utf8')]).then((data)=>{ console.log(data) // 可能返回 'hello' 也可能返回 'swr' 看哪个返回快就用哪个作为结果 }) // 内部实现 Promise.race = function(promises){ // promises 是一个数组 return new Promise((resolve,reject)=>{ for(let i = 0;i < promises.length;i++){ promises[i].then(resolve,reject) // 和上面Promise.all有点类似 } }) }

 

5、promise.defer = promise.deferred这个语法糖怎么理解呢?

这个语法糖可以简化一些操作,比如:

let fs = require('fs') // 写法一: function read(filePath,encoding){ // 这里的new Promise依然是传递了一个executor回调函数 // 我们该怎样减少回调函数嵌套呢? return new Promise((resolve,reject)=>{ fs.readFile(filePath,encoding,(err,data)=>{ if(err) reject(err) resolve(data) }) }) } // 写法二: // 这样的写法减少了一层回调函数的嵌套 function read(filePath,encoding){ let dfd = Promise.defer() fs.readFile(filePath,encoding,(err,data)=>{ if(err) dfd.reject(err) dfd.resolve(data) }) return dfd.promise } read('./1.txt','utf8').then((data)=>{ console.log(data) })

 

 

五、promise的链式调用

promise的核心在于:链式调用。

promise主要解决两个问题:

(1)回调地狱

(2)并发的异步IO操作,同一时间内把这个结果拿到,比如有两个异步io操作,当这2个获取完毕后,才执行相应的代码

1、回调地狱怎么解决

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpxdwg.html