拉勾教育大前端高薪训练营;
从事前端开发工作三年时间,作为半路出家的小白,基础比较薄弱,一直沉不下心去学习,在拉钩跟着一群大佬们一起学习,慢慢的自己也进入学习的状态,本文是自己的学习笔记,第一次写,写的不好还请大家多多提点。
Promise实例
"
```
const promise = new Promise(function (resolve, reject) {
// 这里用于“兑现”承诺
resolve(100) // 承诺达成
// reject(new Error('promise rejected')) // 承诺失败
})
promise.then(function (value) {
// 即便没有异步操作,then 方法中传入的回调仍然会被放入队列,等待下一轮执行
console.log('resolved', value)
}, function (error) {
console.log('rejected', error)
})
console.log('end')
```
"
实例分析
1. Promise 就是一个类 在执行这个类的时候 需要传递一个执行器进去 执行器会立即执行
2. Promise 中有三种状态 分别为 成功 fulfilled 失败 rejected 等待 pending
pending -> fulfilled
pending -> rejected
一旦状态确定就不可更改
3. resolve和reject函数是用来更改状态的
resolve: fulfilled
reject: rejected
4. then方法内部做的事情就判断状态 如果状态是成功 调用成功的回调函数 如果状态是失败 调 用失败回调函数 then方法是被定义在原型对象中的
5. then成功回调有一个参数 表示成功之后的值 then失败回调有一个参数 表示失败后的原因
6. 同一个promise对象下面的then方法是可以被调用多次的
7. then方法是可以被链式调用的, 后面then方法的回调函数拿到值的是上一个then方法的回调函数的返回值
先新建一个MyPromise.js文件,在文件中声明一个类
```
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
constructor (executor) {
// 捕获执行器错误
try {
executor(this.resolve, this.reject)
} catch (error) {
this.reject(error)
}
}
// 状态
status = PENDING;
// 回调成功返回值
value = undefined;
// 回调失败原因
reason = undefined;
// 成功回调,当一个Promise被多次调用,需要将回调存放在一个数组中
successCallback = [];
// 失败回调,当一个Promise被多次调用,需要将回调存放在一个数组中
failCallback = []
resolve = value => {
// 判断状态是否变更
if (this.status !== PENDING) return
// 将状态改为成功
this.status = FULFILLED
// 保存成功之后的值
this.value = value
// 处理异步情况 判断成功回调是否存在, 如果存在 则调用
// this.successCallback && this.successCallback(this.value)
while(this.successCallback.length) this.successCallback.shift()()
}
reject = reason => {
// 判断状态是否变更,如果状态不是等待,组织变更
if (this.status !== PENDING) return
// 将状态改为成功
this.status = REJECTED
// 保存失败的原因
this.reason = reason
// 处理异步情况 判断失败回调是否存在, 如果存在 则调用
// this.failCallback && this.failCallback(this.value)
while(this.failCallback.length) this.failCallback.shift()()
}
then (successCallback, failCallback) {
// then方法参数为可选
successCallback = successCallback ? successCallback : value => value
failCallback = failCallback ? failCallback : reason => {throw reason}
let promise2 = new MyPromise((resolve, reject) => {
// 判断状态
if (this.status === FULFILLED) {
// 获取成功回调函数的返回值,传递给下一个then,即给Promise2
setTimeout(() => {
try {
let x = successCallback(this.value)
// 判断 x 的值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象 查看promsie对象返回的结果
// 再根据promise对象返回的结果 决定调用resolve 还是调用reject
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0);
} else if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = failCallback(this.reason)
// 判断 x 的值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象 查看promsie对象返回的结果
// 再根据promise对象返回的结果 决定调用resolve 还是调用reject
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0);
} else {
// 当promise传递的是一个异步时,不会立即更改状态
// 需要将成功回调和失败回调存储起来
this.successCallback.push(() => {
setTimeout(() => {
try {
let x = successCallback(this.value)
// 判断 x 的值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象 查看promsie对象返回的结果
// 再根据promise对象返回的结果 决定调用resolve 还是调用reject
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0);
})
this.failCallback.push(() => {
setTimeout(() => {
try {
let x = failCallback(this.reason)
// 判断 x 的值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象 查看promsie对象返回的结果
// 再根据promise对象返回的结果 决定调用resolve 还是调用reject
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0);
})
}
})
return promise2
}
catch (failCallback) {
return this.then(undefined, failCallback)
}
// 不管成功与否,finally方法始终都会调用一次
finally (callback) {
return this.then(value => {
return MyPromise.resolve(callback()).then(() => value)
}, reason => {
return MyPromise.resolve(callback()).then(() => {throw reason})
})
}
// Promise.all()方法接收的参数为一个数组,可以填入任何值,数组的顺序为得到的结果顺序保持一致
// 调用then方法,调用结果都成功,则all方法调用结果为成功,否则即为失败
static all (array) {
let result = []
let index = 0 // 当then方法中出现异步方法时,结果会出现空值的情况
return new MyPromise((resolve, reject) => {
function addData (key, value) {
result[key] = value
index++
if (index === array.length) {
resolve(result)
}
}
for(let i = 0; i < array.length; i++) {
let current = array[i]
if (current instanceof MyPromise) {
current.then(value => addData(i, value), reason => reject(reason))
} else {
addData(i, array[i])
}
}
})
}
// resolver方法的作用是将给定的值转成Promise对象,返回值就是一个Promise对象,包裹这个值
static resolve (value) {
if (value instanceof MyPromise) return value
return new MyPromise(resolve => resolve(value))
}
}
function resolvePromise (promise2, x, resolve, reject) {
// 判断函数是否发生循环调用
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
if (x instanceof MyPromise) {
// Promise对象
// x.then(value => resolve(value), reason => reject(reason))
x.then(resolve, reject)
} else {
// 普通值
resolve(x)
}
}
module.exports = MyPromise;
```
const MyPromise = require('./MyPromise')
const promise = new MyPromise(function (resolve, reject) {
// 异步
// setTimeout(() => {
// resolve('成功')
// // reject('失败')
// }, 2000)
// throw new Error('executor error')
// resolve('成功')
reject('失败')
})
// zhen方法多次调用
// promise.then(value => {
// console.log(value)
// throw new Error('then error')
// }, (reason) => {
// console.log(reason.message, 1)
// }).then(value => {
// console.log(value)
// }, (reason) => {
// console.log(reason.message, 2)
// })
// promise.then(value => {
// console.log(value)
// }, (reason) => {
// console.log(reason)
// })
// promise.then(value => {
// console.log(value)
// }, (reason) => {
// console.log(reason)
// })
// then方法链式调用,要实现这个功能,那么then方法就要返回一个Promise对象
// 将上一个then方法的返回值传递给下一个then方法
// function other () {
// return new MyPromise((resolve, reject) => {
// resolve('other')
// })
// }
// promise.then(value => {
// console.log(value)
// return other()
// }).then(value => {
// console.log(value) // 100
// })
// 测试函数发生循环调用的场景
// let p1 = promise.then(value => {
// console.log(value)
// return p1
// })
// p1.then(value => {
// console.log(value)
// }, reason => {
// console.log(reason.message)
// })
// then 链式调用异常捕获
// promise.then(value => {
// console.log(value)
// throw new Error('then error')
// // return 'aaa'
// }, reason => {
// console.log(reason)
// return 10000
// }).then(value => {
// console.log(value)
// }, reason => {
// console.log(reason)
// })
// 验证then方法为可选
// promise.then().then().then(value => console.log(value), reason => console.log(reason))
// 测试promise.all()
function p1 () {
return new MyPromise(function (resolve, reject) {
setTimeout(function () {
resolve('p1')
}, 2000)
})
}
function p2 () {
return new MyPromise(function (resolve, reject) {
setTimeout(function () {
resolve('p2')
}, 2000)
})
}
// 测试静态方法Promise.all()
MyPromise.all(['a', 'b', p1(), p2(), 'd']).then(value => {
console.log(value)
})
// 测试静态方法Promise.resolve
MyPromise.resolve(100).then(value => console.log(value))
function p3 () {
return new MyPromise(function (resolve, reject) {
// resolve('p3 resolve')
reject('p3 error')
})
}
// 测试finally
// p3().finally(() => {
// console.log('finally')
// }).then(value => {
// console.log(value)
// }, reason => {
// console.log(reason)
// })
// 测试catch方法
p3()
.then(value => console.log(value))
.catch(reason => console.log(reason))
注意:node版本较低时无法运行,最好升级到14.15.3