Promise
在我们写函数的时候通常会使用回调函数,当多个函数相互嵌套调用时就可能会产生回调地狱,为了解决这个问题,promise诞生生了,promise可以说是当前最好用的解决回调地狱的方案了。
Promise简介
promise,中文翻译为承诺,有三种状态pending,fulfilled,rejected,初始时状态为pending,成功时状态为fulfilled,失败时状态为rejected,且状态变化不可逆,只能有pending到fulfilled或pending到rejected。
Promise的使用
//调用 Promise 函数
let forget = false
let buyLv = new Promise((resolve, reject) => {
if (forget) {
let data = {
name: 'Lv',
price: 1999
}
resolve(data)
} else {
let err = {
msg: '忘记了'
}
reject(err)
}
})
buyLv.then(fulfilled => {
console.log(fulfilled);
}).catch(rejected => {
console.log(rejected);
})
// forget == false { msg: '忘记了' }
// forget == true { name: 'Lv', price: 1999 }
Promise的链式调用
promise的链式调用会将上一个promise的成功结果作为下一个promise的参数then的结果为第二个promise的resolve。
let forget = true
let buyLv = new Promise((resolve, reject) => {
if (forget) {
let data = {
name: 'Lv',
price: 1999
}
resolve(data)
} else {
let err = {
msg: '忘记了'
}
reject(err)
}
})
let buyAmn = (lv) => {
let Amn = {
name: 'amn',
price: 2548
}
let data = {
lv: lv,
amn: Amn
}
return new Promise((resolve, reject) => {
resolve(data)
reject(Amn)
})
}
buyLv.then(buyAmn).then(fulfilled => {
console.log(fulfilled);
}).catch(rejected => {
console.log(rejected);
})
// forget == true { lv: { name: 'Lv', price: 1999 }, amn: { name: 'amn', price: 2548 } }
// forget == false { msg: '忘记了' }
Promise的实现
es5
// promise 同步
function MyPromise(excutor) {
let self = this;
self.state = 'pending'
self.value = null
self.reason = null
function resolve(value) {
if (self.state === 'pending') {
self.state = "fulfilled"
self.value = value
}
}
function reject(reason) {
if (self.state === 'pending') {
self.state = "rejected"
self.reason = reason
}
}
try {
excutor(resolve, reject)
} catch (error) {
reject(error)
}
}
MyPromise.prototype.then = function (onFullFilled, onRejected) {
onFullFilled = typeof onFullFilled === 'function' ? onFullFilled : function (data) { resolve(data) }
onRejected = typeof onRejected === 'function' ? onRejected : function (err) { throw err }
let self = this;
if (self.state === 'fulfilled') {
onFullFilled(self.value)
}
if (self.state === 'rejected') {
onRejected(self.reason)
}
}
let a = new MyPromise((resolve, reject) => {
resolve(2)
})
a.then(r => {
console.log(r);
})
// 2
//异步
function MyPromise(excutor) {
let self = this;
self.state = 'pending'
self.value = null
self.reason = null
self.onFullFilledCallbacks = []
self.onRejectedCallbacks = []
function resolve(value) {
if (self.state === 'pending') {
self.state = "fulfilled"
self.value = value
self.onFullFilledCallbacks.forEach(fn => fn())
}
}
function reject(reason) {
if (self.state === 'pending') {
self.state = "rejected"
self.reason = reason
self.onFullFilledCallbacks.forEach(fn => fn())
}
}
try {
excutor(resolve, reject)
} catch (error) {
reject(error)
}
}
MyPromise.prototype.then = function (onFullFilled, onRejected) {
onFullFilled = typeof onFullFilled === 'function' ? onFullFilled : function (data) { resolve(data) }
onRejected = typeof onRejected === 'function' ? onRejected : function (err) { throw err }
let self = this;
if (self.state === 'fulfilled') {
onFullFilled(self.value)
}
if (self.state === 'rejected') {
onRejected(self.reason)
}
if (self.state === 'pending') {
self.onFullFilledCallbacks.push(function () {
onFullFilled(self.value)
})
self.onRejectedCallbacks.push(function () {
onRejected(self.reason)
})
}
}
let a = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(2)
}, 1000);
})
a.then(r => {
console.log(r);
})
// 2s后 输出 2
// promise 链式
function MyPromise(excutor) {
let self = this;
self.state = 'pending'
self.value = null
self.reason = null
self.onFullFilledCallbacks = []
self.onRejectedCallbacks = []
function resolve(value) {
if (self.state === 'pending') {
self.state = "fulfilled"
self.value = value
self.onFullFilledCallbacks.forEach(fn => fn())
}
}
function reject(reason) {
if (self.state === 'pending') {
self.state = "rejected"
self.reason = reason
self.onFullFilledCallbacks.forEach(fn => fn())
}
}
try {
excutor(resolve, reject)
} catch (error) {
reject(error)
}
}
MyPromise.prototype.then = function (onFullFilled, onRejected) {
onFullFilled = typeof onFullFilled === 'function' ? onFullFilled : function (data) { resolve(data) }
onRejected = typeof onRejected === 'function' ? onRejected : function (err) { throw err }
let self = this;
if (self.state === 'fulfilled') {
return new MyPromise((resolve, reject) => {
try {
let x = onFullFilled(self.value)
x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
} catch (error) {
reject(error)
}
})
}
if (self.state === 'rejected') {
return new MyPromise((resolve, reject) => {
try {
let x = onRejected(self.value)
x instanceof MyPromise ? x.then(resolve, reject) : reject(x)
} catch (error) {
reject(error)
}
})
}
if (self.state === 'pending') {
self.onFullFilledCallbacks.push(function () {
return new MyPromise((resolve, reject) => {
try {
let x = onFullFilled(self.value)
x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)
} catch (error) {
reject(error)
}
})
})
self.onRejectedCallbacks.push(function () {
return new MyPromise((resolve, reject) => {
try {
let x = onRejected(self.value)
x instanceof MyPromise ? x.then(resolve, reject) : reject(x)
} catch (error) {
reject(error)
}
})
})
}
}
let a = new MyPromise((resolve, reject) => {
resolve(2)
})
let b = (b) => {
return new MyPromise((resolve, reject) => {
if (b) {
resolve(b + '8')
} else {
reject('b-')
}
})
}
let c = (c) => {
return new MyPromise((resolve, reject) => {
if (c) {
resolve(c + '8ppp')
} else {
reject('b-')
}
})
}
a.then(b).then(c).then(r => {
console.log(r);
})
// 288ppp
es6
// 同步
class MyPromise {
constructor(executor) {
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
let resolve = (value) => {
this.state = 'fulfilled'
this.value = value
}
let reject = (reason) => {
this.state = 'rejected'
this.reason = reason
}
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
then(onFullFilled, onRejected) {
if (this.state === 'fulfilled') {
onFullFilled(this.value)
}
if (this.state === 'rejected') {
onRejected(this.reason)
}
}
}
// 异步
class MyPromise {
constructor(executor) {
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
this.onFullFilledCallbacks = [];
this.onRejectedCallbacks = []
let resolve = (value) => {
this.state = 'fulfilled'
this.value = value
this.onFullFilledCallbacks.forEach(fn => fn())
}
let reject = (reason) => {
this.state = 'rejected'
this.reason = reason
this.onRejectedCallbacks.forEach(fn => fn())
}
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
then(onFullFilled, onRejected) {
if (this.state === 'fulfilled') {
onFullFilled(this.value)
}
if (this.state === 'rejected') {
onRejected(this.reason)
}
if (this.state === 'pending') {
this.onFullFilledCallbacks.push(() => {
onFullFilled(this.value)
})
this.onRejectedCallbacks.push(() => {
onRejected(this.reason)
})
}
}
}
// 链式
class MyPromise {
constructor(executor) {
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
this.onFullFilledCallbacks = [];
this.onRejectedCallbacks = []
let resolve = (value) => {
this.state = 'fulfilled'
this.value = value
this.onFullFilledCallbacks.forEach(fn => fn())
}
let reject = (reason) => {
this.state = 'rejected'
this.reason = reason
this.onRejectedCallbacks.forEach(fn => fn())
}
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
then(onFullFilled, onRejected) {
onFullFilled = isFunction(onFullFilled) ? onFullFilled : data => data
onRejected = isFunction(onRejected) ? onRejected : err => {
throw err;
}
const MyPromise2 = new MyPromise((resolve, reject) => {
let x;
if (this.state === 'fulfilled') {
setTimeout(() => {
try {
x = onFullFilled(this.value)
// resolve(x)
resolvePromise(MyPromise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0);
}
if (this.state === 'rejected') {
setTimeout(() => {
try {
x = onRejected(this.reason)
resolvePromise(MyPromise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0);
}
if (this.state === 'pending') {
this.onFullFilledCallbacks.push(() => {
setTimeout(() => {
try {
x = onFullFilled(this.value)
resolvePromise(MyPromise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0);
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
x = onRejected(this.reason)
resolvePromise(MyPromise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0);
})
}
})
return MyPromise2
}
}
function resolvePromise(MyPromise2, x, resolve, reject) {
let called;
if (MyPromise2 === x) {
return reject(new TypeError('typeError'))
}
if ((typeof x === 'object' && x != null) || typeof x === 'function') {
try {
let then = x.then
if (typeof then === 'function') {
then.call(x, y => {
if (called) return
called = true
resolvePromise(MyPromise2, y, resolve, reject)
}, r => {
if (called) return
called = true
reject(r)
})
} else {
if (called) return
called = true
resolve(x)
}
} catch (error) {
if (called) return
called = true
reject(error)
}
} else {
resolve(x)
}
}
const isFunction = (fn) => typeof fn === 'function';
let forget = true
let buyLv = new MyPromise((resolve, reject) => {
if (forget) {
let data = {
name: 'Lv',
price: 1999
}
resolve(data)
} else {
let err = {
msg: '忘记了'
}
reject(err)
}
})
let buyAmn = (lv) => {
let Amn = {
name: 'amn',
price: 2548
}
let data = {
lv: lv,
amn: Amn
}
return new MyPromise((resolve, reject) => {
if (forget) {
resolve(data)
}
else {
reject(Amn)
}
})
}
buyLv.then(buyAmn).then(fulfilled => {
console.log(fulfilled, 'p');
}, r => {
console.log(r, 'r');
})
// { lv: { name: 'Lv', price: 1999 }, amn: { name: 'amn', price: 2548 } } p
Promise all
promise all方法是对多个promise的判断,返回一个promise对象,当多个promise都正确的返回所有promise的resolve的值,当其中有一个错误时返回错误的promise的reject的值。
let forget = true
let p1 = new Promise((resolve, reject) => {
resolve(1)
})
let p2 = new Promise((resolve, reject) => {
if (forget) {
resolve('a')
} else (
reject('b')
)
})
let p3 = new Promise((resolve, reject) => {
resolve(2)
})
Promise.all([p1, p2, p3]).then(r => {
console.log(r);
}, e => {
console.log(e);
})
// forget === true [ 1, 'a', 2 ]
// forget === false b
Promise all 实现
Promise.all2 = function (promises) {
return new Promise(function (resolve, reject) {
const len = promises.length;
let count = 0;
results = new Array(len);
for (let i = 0; i < len; i++) {
Promise.resolve(promises[i]).then((value) => {
count++;
results[i] = value;
if (count == len) {
return resolve(results);
}
}, (reason) => {
return reject(reason);
})
}
})
}
参考视频
【全网首发:更新完】promise源码实现
ES6_Promise(3)手写一个Promise(一)
欢迎评论留言交流!