promise
引用类型Promise,翻译期约(承诺),是一种异步编程结局方案。当我们许下承诺,代表着未来的不确定性(pending),当我们实现时,承诺变为成功(fulfilled)。当我们未能实现时,承诺变为失败(rejected)。
通过new实例化,创建时传入executor函数参数,此时承诺状态为待定。
let promise = new Promise(()=>{})
一、承诺的状态机
- 待定 pending
- 成功 fulfilled
- 失败 rejected
待定是承诺的初始状态,处于待定时可以兑现承诺,变为成功或失败。但是兑现承诺这一过程是不可逆的,且仅能改变一次。promise是无法通过js访问的,因为故意为了和同步代码隔离开。
二、执行器executor
执行器函数是同步执行的,并且在创建完成后立即执行。
let p1 = new Promsie((resolve,reject) => console.log('promise'))
console.log('hello')
承诺的状态只能在内部执行器中改变,控制承诺的状态改变是通过调用两个函数参数实现。这两个函数通常命名为resolve()和reject()。
resolve()
调用resolve()会将状态从pending切换到成功,调用resolve(value)时可以传入一个value
let promise = new Promise((resolve, reject)=>{
console.log('promise')
resolve("成功"); // 调用 resolve 方法
})
console.log('ok', promise)
// 执行结果:
promise
ok Promise { '成功' }
reject()
调用reject()则会将状态从pending切换到失败并且抛出错误,调用reject(reason)时可以传入一个reason
let promise = new Promise((resolve, reject)=>{
console.log('promise')
reject("失败"); // 调用 reject 方法
})
console.log('ok', promise)
// 执行结果:
promise
ok Promise { <rejected> '失败' }
三、Promise 静态 API(类方法)
Promise 共有 4 个静态方法,分别是:resolve、reject、all、race;
Promise.resolve()
创建并返回一个成功状态的 Promise 实例,并将传入的参数作为返回值
let p1 = new Promise((resolve,reject)=> resolve())
let p2 = Promise.resolve() // 两种方法一样,直接实例化一个成功的Promise
使用这个静态方法可以将任意值转换为一个Promise。
// Chrome控制台打印测试
// 返回传入传入Promise的第一个参数
Promise.resolve()
// Promise {<fulfilled>: undefined}
Promise.resolve(666)
// Promise {<fulfilled>: 666}
// 多余参数会被忽略
Promise.resolve(1,2,3)
// Promise {<fulfilled>: 1}
// 传入的参数为Promise,那就是个空包装,Promise.resolve()是一个幂等的方法
// *tips:幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数。 这些函数不会影响系统状态,也不用担心重复执行会对系统造成改变*
Promise.resolve(Promise.resolve(99999))
// Promise {<fulfilled>: 99999}
// 由于幂等性会保留传入Promise的状态
Promise.resolve(new Promise(()=>{}))
// Promise {<pending>}
// 错误对象也能包装,虽然有点反常理
Promise.resolve(new Error('出错啦'))
// Promise {<fulfilled>: Error: 出错啦
// at <anonymous>:1:17}
Promise.reject()
Promise.reject():创建并返回一个失败状态的 Promise 实例,并异步抛出一个错误
let p1 = new Promise((resolve,reject)=> reject())
let p2 = Promise.reject() // 两种方法一样,直接实例化一个失败的承诺
Promise.reject()
// Promise {<rejected>: undefined}
// VM1521:1 Uncaught (in promise) undefined
Promise.reject(666)
// Promise {<rejected>: 666}
// VM1580:1 Uncaught (in promise) 666
Promise.reject(1,2,3)
// Promise {<rejected>: 1}
// VM1647:1 Uncaught (in promise) 1
// 这里有所不同,Promise.reject()并没有幂等性
Promise.reject(Promise.resolve(99999))
// Promise {<rejected>: Promise}
// VM1699:1 Uncaught (in promise) Promise {<fulfilled>: 99999}
Promise.all()
Promise.all():传入一个由Promise组成的数组,返回一个新的Promise实例,只要数组中有一个失败就返回失败的Promise实例。
// 两个全部成功后才会返回成功的Promise,如果出现pending则返回pending
let ppp =Promise.all([
Promise.resolve(),
new Promise((resolve,reject)=> setTimeout(()=>resolve(),1000))
])
console.log(ppp); // Promise {<pending>}
setTimeout(() => {
console.log('1秒后',ppp); // Promise {<fulfilled>: Array(2)}
}, 1000);
// 只要有一个失败,则返回失败的Promise
Promise.all([
Promise.resolve(3),
Promise.reject(666),
Promise.resolve(4)
])
// Promise {<rejected>: 666}
Promise.all([
Promise.resolve(3),
Promise.resolve(),
Promise.resolve(4),
])
// Promise {<fulfilled>: Array(3)}
// [[Prototype]]: Promise
// [[PromiseState]]: "fulfilled"
// [[PromiseResult]]: Array(3)
// 0: 3
// 1: undefined
// 2: 4
// 如果有Promise拒绝,则返回失败并将参数作为错误的原因
// 以下操作没有报出错误,说明第二个Promise仍旧进行了,只是被静默处理了。
let pp = Promise.all([
Promise.reject(3),
new Promise((resolve,reject)=> setTimeout(()=> reject(),1000))
])
pp.catch(reason => setTimeout(()=> console.log(reason)))
Promise.race()
Promise.race():传入一个由Promise组成的数组,返回一个最先成功或拒绝的Promise。无论最先落定的是成功或拒绝的,都会包装值或理由并返回新的Promise。
// 成功先发生的,超时后失败被忽略
let p1 = Promise.race([
Promise.resolve(666),
new Promise((resolve,reject)=> setTimeout(()=>reject(),1000))
])
// 失败先发生的,超时后成功被忽略
let p2 = Promise.race([
Promise.rejct(666),
new Promise((resolve,reject)=> setTimeout(()=>resolve(),1000))
])
// Promise {<fulfilled>: 1}
let p3 = Promise.race([
Promise.resolve(1),
Promise.resolve(2),
Promise.resolve(3)
])
// 如果有Promise拒绝,之后拒绝的Promise不会影响最终Promise的理由
// 以下操作没有报出错误,说明第二个Promise仍旧进行了,只是被静默处理了。
let 4 = Promise.race([
Promise.reject(3),
new Promise((resolve,reject)=> setTimeout(()=> reject(),1000))
])
pp.catch(reason => setTimeout(()=> console.log(reason)))
四、Promise 实例 API(原型方法)
Promise.prototype.then()
then()方法接受两个函数参数:onResolved处理程序和onRejected处理程序,分别在Promise进入成功或失败时执行。then()方法返回一个新的Promise实例。
- 如果then指定的回调返回的是非Promise值a,走成功,成功的值是a。
- 如果then指定的回调返回的是Promise实例,新的Promise状态和值和上次一致(幂等方法)。
- 如果then指定的回调返回的是新Promise状态为rejected,则失败的reason为异常。
let p1 = new Promise((resolve,reject)=> setTimeout(()=>reject(),3000))
p1.then(null, ()=> setTimeout(()=>console.log(666),1000)) // 良好的习惯,空值占位
// 666
// Promise {<rejected>: undefined}
onResolved(),onResolved处理程序返回的值会被Promise.resolve()包装生成新的的Promise
let p1 = Promise.resolve('hello')
// 如果没有显式的返回值,若then指定的回调是Promise实例,新的Promise的状态和值会直接传递
let p2 = p1.then() // Promise {<fulfilled>: 'hello'}
let p3 = p1.then(()=> undefined) // Promise {<fulfilled>: undefined}
let p4 = p1.then(()=> {}) // Promise {<fulfilled>: undefined}
let p5 = p1.then(()=> Promise.resolve()) // Promise {<fulfilled>: undefined}
// 如果有显示的返回值
let p6 = p1.then(()=> 'bar') // Promise {<fulfilled>: 'bar'}
let p7 = p1.then(()=> Promise.resolve('bar')) // Promise {<fulfilled>: 'bar'}
// 如果传入是Promise实例,则新的Promise状态和值和上次一致(幂等方法)
let p8 = p1.then(()=> new Promise(() => {})) // Promise {<pending>}
let p9 = p1.then(()=> Promise.reject()) // Promise {<rejected>: undefined}
// 抛出异常会返回拒绝的Promise
let p10 = p1.then(()=> { throw 'baz' }) // Promise {<rejected>: 'baz'}
// 注意!返回错误值不会触发上面的拒绝行为,而是把错误对象包装在一个成功的Promise中
let p11 = p1.then(()=> Error('qux')) //Promise {<fulfilled>: Error: qux
onRejected()同onResolved类似,onRejected处理程序返回的值会被Promise.resolve()包装
let p1 = Promise.reject('foo')
let p2 = p1.then() // Promise {<rejected>: 'foo'}
let p3 = p1.then(null, ()=> undefined) // Promise {<fulfilled>: undefined}
let p4 = p1.then(null, ()=> {}) // Promise {<fulfilled>: undefined}
let p5 = p1.then(null, ()=> Promise.resolve()) // Promise {<fulfilled>: undefined}
let p6 = p1.then(null, ()=> 'bar') // Promise {<fulfilled>: 'bar'}
let p7 = p1.then(null, Promise.resolve('bar')) // Promise {<rejected>: 'foo'}
let p8 = p1.then(null, ()=> new Promise(()=> {})) // Promise {<pending>}
let p9 = p1.then(null, ()=> Promise.reject()) // Promise {<rejected>: undefined}
let p10 = p1.then(null,()=> { throw 'baz'}) // Promise {<rejected>: 'baz'}
let p11 = p1.then(null, ()=> Error('qux')) // Promise {<fulfilled>: Error: qux
Promise.prototype.catch()
catch()方法用于给Promise添加失败的回调。catch方法只接受一个参数:onRejected处理程序。catch相当于一个语法糖,调用他相当于Promise.prototype.then(null, onRejected)
let p = Promise.reject()
let onRejected = (e)=>{
setTimeout(()=> console.log('rejected'),1000)
}
// 以下两种方式相同
p.then(null,onRejected)
p.catch(onRejected)
catch方法返回一个新的实例
let p1 = new Promise(()=>{}) //
let p2 = p1.catch() // Promise {<pending>}
Promise.prototype.finally()
finally()方法用于给Promise添加onFinally处理程序,这个程序在Promise转化为成功或失败时都会执行。onFinally这个程序设计为与promise状态无关的方法,所以它没法知道promise是成功还是失败,它只会表现为父级Promise的传递,这个方法主要用于添加清理代码。
let p1 = Promise.resolve()
let p2 = Promise.reject()
let onFinally = function(){
setTimeout(()=>{console.log('fianlly')},1000)
}
p1.finally(onFinally) // fianlly
p2.finally(onFinally) // finally
五、简单的实现的Promise
// 定义promise中的三种状态
const STATUS_PENDING = "pending";
const STATUS_FULFILLED = "fulfilled";
const STATUS_REJECTED = "rejected";
// 定义promise的类
class myPromise {
//class的构造函数,接受新建实例时的参数:executor在promise中是一个函数
constructor(executor) {
//初始化该class中的初始状态
this.status = STATUS_PENDING;
//定义class中成功(res)和失败(err)时的变量值
this.res = "";
this.err = "";
//promis异步中最重要的异步,定义成功和错误函数存储的数组,存放异步时还没有执行的操作
this.onResCallbacks = [];
this.onErrCallbacks = [];
//定义该构造函数constructor定义域中的变量resolve
let resolve = (res) => {
// 首先判断该class中的状态,只有状态为pending时才能转化class转态为fulfilled或者rejected
if (this.status === STATUS_PENDING) {
//修改class的转态为fulfilled,也就表示不会转进行其他转态的转化了
this.status = STATUS_FULFILLED;
//将成功(resolve)状态下的值赋给class的成功返回res
this.res = res;
//此时状态由pending转为fulfilled,执行之前在then中存放的需要执行的异步操作,promise的then中参数res接受结果
this.onResCallbacks.forEach(fn => fn());
}
};
//定义该构造函数constructor定义域中的变量reject
let reject = (err) => {
// 首先判断该class中的状态,只有状态为pending时才能转化class转态为fulfilled或者rejected
if (this.status === STATUS_PENDING) {
//修改class的转态为rejected,也就表示不会转进行其他转态的转化了
this.status = STATUS_REJECTED;
//将失败(reject)状态下的值赋给class的失败返回err
this.err = err;
//此时状态由pending转为rejected,执行之前在catch中存放的需要执行的异步操作,promise的catch中参数err接受结果
this.onErrCallbacks.forEach((fn) => fn());
}
};
//按照promise中的逻辑,在调用时就立即执行了,所以在手写的myPromise创建构造函数constructor时就执行executor
try {
//执行参入的函数,并将上述定义的resolve和reject作为参数传入
executor(resolve, reject);
} catch (err) {
//报错时调用失败的状态函数
reject(err);
}
}
//在class中定义promise的成功状态接收函数then,按照promise逻辑,then中传入的一般都是一个函数
then(onRes = () => { }) {
//如果是异步的,此时在constructor中status的状态还没变成fulfilled,所以会跳过onRes调用,没有返回
if (this.status === STATUS_FULFILLED) {
onRes(this.res);
}
//但是我们将此时的异步放入数组存放
if (this.status === STATUS_PENDING) {
this.onResCallbacks.push(() => onRes(this.res));
}
//这步操作保证了then和catch能够在同级一起"."调起,当then上述操作完后,返回class实例,便可以接在后面继续调用catch
return this;
}
//在class中定义promise的失败状态接收函数catch,按照promise逻辑,catch中传入的一般都是一个函数
catch(onErr = () => { }) {
//如果是异步的,此时在constructor中status的状态还没变成rejected,所以会跳过onErr调用,没有返回
if (this.status === STATUS_REJECTED) {
onErr(this.err);
}
//但是我们将此时的异步放入数组存放
if (this.status === STATUS_PENDING) {
this.onErrCallbacks.push(() => onErr(this.err));
}
//这步操作保证了then和catch能够在同级一起"."调起,当catch上述操作完后,返回class实例,便可以接在后面继续调用then
return this;
}
}
//调用自己手写的promise
new myPromise((resolve, reject) => {
// console.log("进入了手写的promise");
//用setTimeOut模拟异步操作
setTimeout(() => {
if (false) {
resolve("输出成功结果resolve");
} else {
reject("输出失败结果reject");
}
}, 2000); //按照js的特性,此时不会等待异步完成,直接调用then或者catch
})
.then((res) => {
console.log("then:", res);
})
.catch((err) => { //return this具体作用体现在这里
console.log("catch:", err);
});
标签:resolve,基础知识,p1,let,promise,reject,Promise,手写
From: https://www.cnblogs.com/wanglei1900/p/17255961.html