Promise的deferred对象详解

前端精髓

共 2714字,需浏览 6分钟

 ·

2022-02-19 02:33

基础知识

简单说,deferred 对象就回调函数解决方案。在英语中,defer的意思是"延迟",所以 deferred 对象的含义就是"延迟"到未来某个点再执行。所以也叫延迟对象。


我们先看一个例子,等待某个异步操作完成去做一些事情:


let p = new Promise((resolve, reject) => {  setTimeout(() => {    console.log('完成')    resolve(1)  }, 1000)})// 等待定时器完成输出okp.then((res) => {  console.log('ok', res)})


我们发现 Promise 和定时器耦合在一起,也就是说定时器必须写在 Promise 里面,因为需要等待定时器完成修改 Promise 的状态。接下来解耦,我们希望外部能控制 Promise 的状态。


let resolveFn // 把resolve保存起来方便外部调用let p = new Promise((resolve, reject) => {  resolveFn = resolve})
setTimeout(() => { console.log('完成') resolveFn(1)}, 1000)
p.then((res) => { console.log('ok', res)})


我们通过一个全局变量把 resolve 保存起来方便外部调用,如果需要的话可以再定义一个变量把 reject 保存起来,由于这里未使用所以省略了。


可能需要3个全局变量,为了防止变量冲突,我们最好通过一个对象来保存。


let deferred = {}deferred.promise = new Promise((resolve, reject) => {  deferred.resolve = resolve  deferred.reject = reject})
setTimeout(() => { console.log('完成') deferred.resolve(1)}, 1000)
deferred.promise.then((res) => { console.log('ok', res)})


Promise 和 Deferred 的整体关系,从上面的代码可以看出,Deferred 主要是用于内部,用于维护异步模型的状态;Promise 则作用于外部,通过 then() 方法暴露给外部以添加自定义逻辑。


Promise/Deferred 模式的API接口和抽象模型都十分简洁。它将业务中不可变的部分封装在了 Deferred 中,将可变的部分交给了 Promise。


项目实战

到目前为止我们已经掌握了 Promise 的 deferred 对象,接下来我们就看看怎么使用吧。


1、减少代码嵌套

let fs = require('fs');
// 实现promise延迟对象,deferlet Deferred = function () { let dfd = {}; dfd.promise = new Promise((resolve, reject) => { dfd.resolve = resolve; dfd.reject = reject; }) return dfd}
// function read () {// return new Promise((resolve, reject) => {// fs.readFile('./a.txt', 'utf8', (err, data) => {// if (!err) resolve(data)// })// })// }// 减少代码嵌套
function read () { let defer = Deferred() fs.readFile('./a.txt', 'utf8', (err, data) => { if (!err) defer.resolve(data) }) return defer.promise}
read().then((data) => { console.log(data)})


2、多个地方想控制1个 Promise 的状态,回调只想执行1次。

let deferred = {}deferred.promise = new Promise((resolve, reject) => {  deferred.resolve = resolve  deferred.reject = reject})// 异步操作的顺序不确定setTimeout(() => {  deferred.resolve()}, 10 * Math.random())
setTimeout(() => { deferred.resolve()}, 10 * Math.random())
// 只要有1个异步操作完成就执行回调deferred.promise.then(() => { console.log('ok')})


3、多个异步之间的协作方案,多个延迟对象配合使用。

let Deferred = function () {  let dfd = {};  dfd.promise = new Promise((resolve, reject) => {    dfd.resolve = resolve;    dfd.reject = reject;  })  return dfd}
let d1 = Deferred()let d2 = Deferred()
Promise.all([d1.promise, d2.promise]).then((res) => { console.log(res) // [ 'Fish', 'Pizza' ]})
d1.resolve( "Fish" )d2.resolve( "Pizza" )


总结:

Deferred对象实现了 Promise,并且将 resolve 和 reject 方法暴露在了构造函数外面,Promise 对象的状态更为灵活。仍然是状态的改变只有一次,之后的更改会忽略。


浏览 22
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报