学习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)) //errPromise.reject('err').catch((err) => console.log(err)) //errtry{    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    */