关于javascript:学习Promise日记

8次阅读

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

学习 Promise 日记

什么是 Promise?

​ promise(翻译:承诺;期待;期约),在《javascript 高级程序设计》这本书叫做“期约”,‘期约’的解释是尚不存在的后果,我的了解是:很期待咱们的约定的后果 (真的很期待能跟她约个好后果,比方结婚、生仔、幸福一辈子,哈哈哈)。然而世事难料,她可能会拒丑,哎,别想太多,不论后果怎么样我都要正确的去面对这些后果。其实我比拟花心,我约完这个还跟另一个女孩有期约,另一个女孩跟我约完又跟其余帅哥有期约 …

​ Promise 是一个 ECMAScript 6 提供的类,目标是更加优雅地书写简单的异步工作。

Promise 状态机

Promise 状态机有三种状态:待定(pending)、兑现(fulfilled 或者 resloved)、回绝(rejected)

callback_pending = (resolve, reject) => {}
callback_resolve = (resolve, reject) => resolve()
callback_reject = (resolve, reject) => reject()
function promise_instance(callback) {return new Promise(callback)
}
console.log(promise_instanc(callback_pending)); // 回调函数未执行 resolve, 或者 reject,状态处于 pending 状态
console.log(promise_instanc(callback_resolve)); // 回调函数执行了 resolve,状态处于兑现(resloved)状态
console.log(promise_instanc(callback_reject));  // 回调函数执行了 reject,状态处于回绝(rejected)状态 

Promise.prototype 办法中的 then()、catch()、finally(),作为 Promise 在回绝或者兑现状态的处理程序

Promise.resolve()

Promise 并不是开始就必须处于 pending 的状态而后转换为兑现(resloved)、回绝(rejected)。通过 Promise.resolve() 这个静态方法,能够把任何值转换为一个 resolved 状态的 Promise

// 以下两行 p1 和 p2 的打印后果是一样的
let p1 = new Promise((resolve, reject) => resolve(1))
let p2 = Promise.resolve(1)
console.log(p1)//Promise {<resloved>: 1}
console.log(p2) //Promise {<resloved>: 1}

这个办法如果传入的参数是一个 Promise,那么它的行为就相似于一个空包装,最终的值是传入的参数的值,能够说是一个幂等函数

let p = Promise.resolve(1)
console.log(p === Promise.resolve(p));// true

依据上条,这个幂等函数会保留传入 Promise 的状态

let p = new Promise(() => {})
    console.log(Promise.resolve(p));//Promise {<pending>}
    console.log(p);////Promise {<pending>}

它能够包装任何非 Promise 的值,包含谬误对象

let p = Promise.resolve(new Error('error'))
    console.log(p);//Promise {<fulfilled>: Error: error

Promise.reject()

与 Promise.resolve() 相似,Promise.reject() 能够把任何值转换为一个 rejected 状态的 Promise, 并且抛出一个异步谬误,然而这个谬误不能通过 try/catch 捕捉, 只能通过 Promise 的.then() 或者.catch() 的办法进行捕捉。但它不像 Promise.resolve() 是一个幂等办法,就算传入的是 Promise.reject(),它返回的也是一个回绝理由为 Promise.reject()

Promise.reject('err').then(null, (err) => console.log(err)) //err
Promise.reject('err').catch((err) => console.log(err)) //err
try{Promise.reject('err')
  }catch(err){// 捕捉不到,没有执行 catch,是因为它没有通过异步模式捕捉
    console.log(err);
  }

Promise.prototype.then()

Promise.prototype.then() 是 Promise 实例增加处理程序的次要办法,.then() 能够接管两个参数,别离为 resolved 状态时的回调函数、rejected 状态的回调函数。

 //resolve 先执行
new Promise((resolve, reject) => {resolve('我给你兑现')// 首先被执行了,转换为 resolve 状态
    reject('我回绝你')// 如果 resolve 先执行,不会被执行了,会被静默疏忽,因为状态只能转换一次
  }).then((res) => console.log(res), //res 拿到 resolve 传的参数,输入:这是兑现执行的
    (rej) => console.log(rej), // 这里不执行
  )
//reject 先执行
new Promise((resolve, reject) => {reject('我回绝你')// 首先被执行了,转换为 reject 状态
    resolve('我给你兑现')// 如果 reject 先执行,不会被执行了,会被静默疏忽,因为状态只能转换一次
  }).then((res) => console.log(res), // 这里不执行
    (rej) => console.log(rej), //rej 拿到 reject 传的参数,输入:这是拒绝执行的
  )

Promise.prototype.catch()

​ Promise.prototype.catch() 是.then(null, () => {}} 的语法糖,用来捕捉回绝理由的

new Promise((resolve, reject) => {reject('我回绝你')
  }).catch(err => console.log(err) )// 我回绝你 

Promise.prototype.finally()

Promise.prototype.finally() 是 Promise 无论转换成什么状态都会被执行,它也无奈晓得是 Promise 处于什么状态。

后续 finally() 包裹的内容,除了 pending 状态或者抛出了谬误会返回 Promise<pending> 或者 Promise<reject>,其余返回的是 Promise<resovle>

pending 状态时,无论什么时候 resolve 或者 reject,都会在 resolve 或者 reject 时返回 Promise

let p2 = p1.finally(() => new Promise(() =>setTimeout(() => resolve('bar'),100)));
setTimeout(console.log(p), 0);//Promise <pending>
setTimeout(() => setTimeout(console.log(p2),200));// 上一个 setTimeou 100ms 执行完回调后才到这个 setTimeout 回调,这时拿到的 p2 曾经 resolve,输入:Promise <resolved>:foo

Promise 与同步代码执行程序

Promise 被转变状态之后,并不会马上执行,它的处理程序是会被推动音讯队列中。所以在同步过程执行完,它的处理程序才会执行。

let p =let Promise.resolve();
p.then(()=> console.log('Promise'));
console.log('同步输入')

// 它的输入程序为:先输入同步输入,再输入 Promise

Promise 链式调用

Promise 能链式调用是因为 then()、catch()、finally() 都会返回一个新的 Promise

如果你真的弄懂了 Promise 状态解决机制,对上面代码的执行后果就能一目了然了。

let p = new Promise((resolve, reject) => {resolve('resolve')
  })
  .then(res => console.log(res))//resolve
  .then(res => console.log(res)) //undefined
  .then(res => console.log(res))//undefined
  .then(() => Promise.reject('reject'))
  .catch(e => {console.log(e);
    return 8// 相当于 return Promise.resolve(8)
  }) //reject
  .then((res) => {console.log(res);
    return Error('error') // 相当于 return Promise.reject('error') 抛出异步谬误
  })
  .then(res => console.log(res),// 不执行
    err => console.log(err) // 输入 error
  )
  .finally(f => console.log(f))// 最初必定会执行,f 得不到任何值,输入 undefined

Promise.all()

Promise.all() 的参数是一个数组,只有当数组的所有 Promise 为 resolved 时才执行.then(), 否则执行.catch()

 Promise.all([Promise.resolve(1),
   Promise.resolve(2),
   new Promise((resolve,reject) => resolve(3))
 ]).then(result => console.log(result) ) //[1, 2, 3]

// 处理程序第一个被 reject 的
Promise.rece([Promise.resolve(1),
    Promise.reject(2),
    Promise.reject(3),
    new Promise((resolve, reject) => resolve(3))
  ]).then(result=> console.log(result)) // 不执行
  .catch(e => console.log(e)) // 失去第一个被 rejected 的值,输入:2

Promise.race()

Promise.race() 的参数也是一个数组,会返回第一个先被转变状态的 Promise。

//resolve(100) 先被执行的状况
Promise.race([new Promise((resolve, reject) => setTimeout(()=> resolve(300), 300)),
    new Promise((resolve, reject) => setTimeout(() => resolve(200), 200)),
    new Promise((resolve, reject) => setTimeout(() => resolve(100), 100)),
  ]).then(result=> console.log(result)) // 100
  .catch(e => console.log(e)) // 不执行
//reject(100) 先被执行的状况
  Promise.race([new Promise((resolve, reject) => setTimeout(() => resolve(300), 300)),
    new Promise((resolve, reject) => setTimeout(() => resolve(200), 200)),
    new Promise((resolve, reject) => setTimeout(() => reject(100), 100)),
  ]).then(result => console.log(result)) // 不执行
    .catch(e => console.log(e)) //100

Promise 链式调用的合成

Promise.then()+ Array.reduce() 能够把多层链式调用简化为一个通用函数 compose, 这样使代码更加简洁

function add2(x) {return (x+2)};
function add3(x) {return (x + 3) }
function add4(x) {return (x + 4) }
function compose(...args) {return x => args.reduce((promise, fn) => promise.then(fn),Promise.resolve(x))
}

Promise 的扩大

Promise 的进度告诉

class TrackablePromise extends Promise {constructor (executor) {const notifyHandlers = [];
    super((res, rej) => {return executor(res, rej, (status) => {notifyHandlers.map((handlder) => handlder(status));
      })
    }) 
    this.notifyHandlers = notifyHandlers;
  }
  notify(notifyHandler) {this.notifyHandlers.push(notifyHandler);
    return this
  }
}
let p = new TrackablePromise((res, rej, notify) => {function countdown(x) {if(x > 0) {notify(`${20*x}% remaining`);
      setTimeout(() => countdown(x-1), 1000)
    }else {res();
    }
  }
  countdown(5);
})
p.notify((x) => setTimeout(console.log, 0, 'progress', x));
p.then(() => setTimeout(console.log, 0, 'completed'));

/*         
    (1 秒后打印):progress 80% remaining
    (2 秒后打印):progress 60% remaining
    (3 秒后打印):progress 40% remaining
    (4 秒后打印):progress 20% remaining
    (5 秒后打印):completed    
*/
正文完
 0