Promise周边方法

3次阅读

共计 3225 个字符,预计需要花费 9 分钟才能阅读完成。

上面了解 promise a+ 之后,那么这篇文章就是扩展一下 promise 的周边方法

promisify 的实现

promisify 是 node 提供的一个方法用来解决回调嵌套问题,用起来很方便; 我项目中有两个文件,一个为 name.txt, 里面存放的是 age.txt,另一个为 age.txt 里面的内容为 18,这里就是为了演示多个异步接收返回值问题,现在让我们看看原来获取异步返回值,毫无疑问这样非常的恶心

原始调用异步
let fs= require('fs');
fs.readFile('./name.txt', 'utf8', function (err, data) {console.log(data);//age.txt
    if (err) {console.log(err);
    } else {fs.readFile(data, 'utf8', function (err, data) {if (err) {console.log(err);
            } else {console.log(data);
            }
        })
    }

});

既然已经看到他的恶心之处了,那我们想办法优化一下,封装一个公共函数:

read 公共方法的封装
function read(...args) {let dfd = Promise.defer();// 这个是我们上一账封装的 promise 中的方法
    fs.readFile(...args, function (err, data) {if (err) dfd.reject(err);
        dfd.resolve(data)
    });
    return dfd.promise
}

使用的时候如下:

read('./name.txt', 'utf8').then(data => {console.log(data);
    return read(data, 'utf8')
}).then(data => {console.log(data);
})

上面这种看起来不错,但是还是不能让人满意,因为他的功能太单一了,这时候我们的主角 promisify 就上场了,那么我们先来看一看它原本是怎么用的:

promisify 使用
let {promisify} = require('util');//node 提供的方法库
let readFile = promisify(fs.readFile); // 用什么方法就把对应的方法传进去,肥肠的方便

readFile('./name.txt', 'utf8').then(data => {console.log(data);//age.txt
    return readFile(data, 'utf8')
}).then(data => {console.log(data);//18
})
promisify 实现

上面的用法很简单,那么我们简单的实现一下吧, 用法和以上相同

function promisify(fn) {// 你传进来的方法 fs.readFile/fs.writeFile...
    return function (...args) {// 传进来的路径,格式
        // 既然有 then 那么他就是一个 promise
        return new Promise((resolve, reject) => {fn(...args,function (err,data) {if(err) reject(err)
                resolve(data)
            })
        })
    }
}

promise.all 实现

promise.all 方法传入一个数组,最后按顺序返回一个数组,如果数组中其中一项为失败那么就是失败态
用法:

Promise.all([1, readFile('./name.txt', 'utf8'), 2, readFile('./age.txt', 'utf8'), 3]).then(data => {console.log(data); //[1,'age.txt'(name 中写的内容),2,'18'(age 中写的内容),3]
});

实现:

// 校验传进来的值是不是 promise,是返回 true,否则返回 false
function isPromise(x) {if((typeof x==='object'&&x!=null)||typeof x ==='function'){if(typeof  x.then ==='function'){return true}
    }
    return false
}

Promise.all = function (arr) {
      // 返回一个 promise
    return new Promise((resolve, reject) => {let ary = [];
        // 用来记录返回数组的长度
        let idx=0;
        let insertAry=(value,index)=>{ary[index]=value;
            if(++idx===arr.length){resolve(ary)
            }
        };
       // 循环传入的数组
        for (let i = 0; i < arr.length; i++) {let currentValue = arr[i];
            if (isPromise(currentValue)) {
            // 如果是 promise
                currentValue.then(y=>{insertAry(y,i)
                },reject)
            } else {
            // 如果是普通值
                insertAry(currentValue,i)
            }
        }
    })
};

直接调用 promise.reslove 和 promise.reject

用法:

Promise.resolve(1).then(data=>{console.log(data)})

实现:

Promise.resolve=function(value){return new Promise((resolve,reject)=>{resolve(value)
    })
};

catch

catch 就是一个没有成功参数的 then, 在上一篇文章封装好的 Promise 中加入一个 catch 函数

 catch(fn){//catch 接收一个函数
      return  this.then(null,fn)// 返回的也是 promise
    }

promise 中的 finally

不管成功还是失败都会执行,并且返回一个 promise 以供 then 调用,也是 then 的另一种执行形式
用法:

Promise.resolve(readFile('./name.txt','utf8')).then(data=>{// console.log(data);
    return data
}).catch(err=>{console.log(err);
}).finally(data=>{console.log('finally');
}).then(data=>{console.log(data);
});

实现:
在上篇封装的 promise 中加入以下方法

finally(callback){

   return this.then(res => Promise.resolve(callback()).then(() => res),
        err => Promise.resolve(callback()).then(() => { throw err;})
    )
}

promise 中的 race

用法:

Promise.race([readFile('./name.txt','utf8'),readFile('./age.txt','utf8')]).then(data=>{console.log(data);
});

实现:

Promise.race=function (arr) {return new Promise((resolve,reject)=>{for (let i = 0; i < arr.length; i++) {let currentValue=arr[i];
            // 这个 isPromise 用的是上面 promise.all 文本块的方法
            if(isPromise(currentValue)){
                currentValue.then(data=>{resolve(data)
                },reject)
            }else {resolve(currentValue)
            }
        }
    })
};
正文完
 0