предисловие
Привет всем, я Линь Сансинь, я думаю, что все использовали его в повседневной разработке.Promise, у меня всегда была мечта, чтоСамыми простыми словами расскажи самые сложные знания, поэтому я поставилЛегко понятьПоставьте это на первое место, сегодня я возьму вас, чтобы добиться следующего почеркаОбещай это, Я думаю, все поймут с первого взгляда.
решить и отклонить
Давайте посмотрим на кусок кода Promise:
let p1 = new Promise((resolve, reject) => {
resolve('成功')
reject('失败')
})
console.log('p1', p1)
let p2 = new Promise((resolve, reject) => {
reject('失败')
resolve('成功')
})
console.log('p2', p2)
let p3 = new Promise((resolve, reject) => {
throw('报错')
})
console.log('p3', p3)
Так что же будет на выходе? Пожалуйста, посмотри:
Здесь раскрываются четыре точки знаний:
- 1. Казнен
resolve
, состояние Promise станетfulfilled
- 2. Казнен
reject
, состояние Promise станетrejected
- 3. Обещания начинаются только с
第一次为准
, первый успешный永久
дляfulfilled
, первая ошибка всегда будет указываться какrejected
- 4. В обещании
throw
Если слова эквивалентны выполнениюreject
Затем мы поставили эти четыре знания шаг за шагом, чтобы добиться этого! ! !
1. Решить и отклонить
Всем следует обратить внимание: начальное состояние Promisepending
Важным шагом здесь являетсяresolve和reject的绑定this
, зачем привязыватьthis
Шерстяная ткань? Это для решения и отклоненияthis指向
всегда указывать на текущийMyPromise实例
, чтобы предотвратить изменения при изменении среды выполнения функции
class MyPromise {
// 构造方法
constructor(executor) {
// 初始化值
this.initValue()
// 初始化this指向
this.initBind()
// 执行传进来的函数
executor(this.resolve, this.reject)
}
initBind() {
// 初始化this
this.resolve = this.resolve.bind(this)
this.reject = this.reject.bind(this)
}
initValue() {
// 初始化值
this.PromiseResult = null // 终值
this.PromiseState = 'pending' // 状态
}
resolve(value) {
// 如果执行resolve,状态变为fulfilled
this.PromiseState = 'fulfilled'
// 终值为传进来的值
this.PromiseResult = value
}
reject(reason) {
// 如果执行reject,状态变为rejected
this.PromiseState = 'rejected'
// 终值为传进来的reason
this.PromiseResult = reason
}
}
Давайте протестируем код:
const test1 = new MyPromise((resolve, reject) => {
resolve('成功')
})
console.log(test1) // MyPromise { PromiseState: 'fulfilled', PromiseResult: '成功' }
const test2 = new MyPromise((resolve, reject) => {
reject('失败')
})
console.log(test2) // MyPromise { PromiseState: 'rejected', PromiseResult: '失败' }
2. Состояние неизменно
На самом деле приведенный выше код проблематичен, в чем проблема? посмотри:
const test1 = new MyPromise((resolve, reject) => {
resolve('成功')
reject('失败')
})
console.log(test1) // MyPromise { PromiseState: 'rejected', PromiseResult: '失败' }
Правильное состояние должно бытьfulfilled
,оказаться成功
, явно нет以第一次为准
Как я уже говорил, промисы начинаются только с第一次为准
, первый успешный永久
дляfulfilled
, первая ошибка всегда будет указываться какrejected
, каков конкретный процесс? Я нарисовал для вас картинку:
Обещания имеют три состояния:
-
pending
: Ожидание, это начальное состояние -
fulfilled
: состояние успеха -
rejected
: статус отказа
Как только состояние изменится сpending
сталиfulfilled或者rejected
, то состояние этого экземпляра Promise мертво.
На самом деле это очень легко реализовать, просто добавьте условие суждения:
resolve(value) {
// state是不可变的
+ if (this.PromiseState !== 'pending') return
// 如果执行resolve,状态变为fulfilled
this.PromiseState = 'fulfilled'
// 终值为传进来的值
this.PromiseResult = value
}
reject(reason) {
// state是不可变的
+ if (this.PromiseState !== 'pending') return
// 如果执行reject,状态变为rejected
this.PromiseState = 'rejected'
// 终值为传进来的reason
this.PromiseResult = reason
}
Давайте посмотрим на эффект:
const test1 = new MyPromise((resolve, reject) => {
// 只以第一次为准
resolve('成功')
reject('失败')
})
console.log(test1) // MyPromise { PromiseState: 'fulfilled', PromiseResult: '成功' }
3. throw
Обещай тамthrow
эквивалентно выполнениюreject
. это использоватьtry catch
охватывать
+ try {
// 执行传进来的函数
executor(this.resolve, this.reject)
+ } catch (e) {
// 捕捉到错误直接执行reject
+ this.reject(e)
+ }
Давайте посмотрим на эффект:
const test3 = new MyPromise((resolve, reject) => {
throw('失败')
})
console.log(test3) // MyPromise { PromiseState: 'rejected', PromiseResult: '失败' }
then
Обычно мы используем метод then следующим образом:
// 马上输出 ”成功“
const p1 = new Promise((resolve, reject) => {
resolve('成功')
}).then(res => console.log(res), err => console.log(err))
// 1秒后输出 ”失败“
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('失败')
}, 1000)
}).then(res => console.log(res), err => console.log(err))
// 链式调用 输出 200
const p3 = new Promise((resolve, reject) => {
resolve(100)
}).then(res => 2 * res, err => console.log(err))
.then(res => console.log(res), err => console.log(err))
Эти знания можно суммировать:
- затем получает два обратных вызова, один
成功回调
,один失败回调
- Когда состояние обещания
fulfilled
воплощать в жизнь成功回调
,дляrejected
воплощать в жизнь失败回调
- Если разрешение или отклонение находится в таймере,
则定时器结束后再执行then
- затем поддержите
链式调用
, затем выполняется следующий受上一次then返回值的影响
Пойдем шаг за шагом, чтобы понять это.
1. Реализуйте затем
then(onFulfilled, onRejected) {
// 接收两个回调 onFulfilled, onRejected
// 参数校验,确保一定是函数
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
if (this.PromiseState === 'fulfilled') {
// 如果当前为成功状态,执行第一个回调
onFulfilled(this.PromiseResult)
} else if (this.PromiseState === 'rejected') {
// 如果当前为失败状态,执行第二哥回调
onRejected(this.PromiseResult)
}
}
Давайте посмотрим на эффект:
// 输出 ”成功“
const test = new MyPromise((resolve, reject) => {
resolve('成功')
}).then(res => console.log(res), err => console.log(err))
2. Таймер ситуации
Выше мы достиглиthen
Основные функции. что если定时器
Как насчет ситуации?
Или этот код, как мы можем гарантировать, что обратный вызов ошибки в then будет выполнен через 1 секунду?
// 1秒后输出 ”成功“
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('失败')
}, 1000)
}).then(res => console.log(res), err => console.log(err))
Мы не можем гарантировать, что функция then будет выполнена через 1 секунду, но мы можем гарантировать, что обратный вызов в then будет выполнен через 1 секунду. Может быть, здесь все немного запутались. Я также использую картинку, чтобы рассказать вам:
То есть в течение этой 1 секунды мы можем сначала сохранить два обратных вызова в then, а затем подождать, пока через 1 секунду не будет выполнено разрешение или отклонение, а затем оценить статус и принять решение о выполнении двух только что сохраненных обратных вызовов. Перезвоните.
Итак, вопрос в том, как мы узнаем, что текущая 1 секунда не была завершена или даже не началась? На самом деле, очень хорошо судить, пока статусpending
, это доказывает, что таймер не истек, потому что если таймер истекает, то состояние точно неpending
, ноfulfilled或者rejected
Так что же используется для сохранения этих обратных вызовов? Рекомендуется использовать数组
, потому что экземпляр обещания может多次then
, используйте массив для сохранения по одному
initValue() {
// 初始化值
this.PromiseResult = null // 终值
this.PromiseState = 'pending' // 状态
+ this.onFulfilledCallbacks = [] // 保存成功回调
+ this.onRejectedCallbacks = [] // 保存失败回调
}
resolve(value) {
// state是不可变的
if (this.PromiseState !== 'pending') return
// 如果执行resolve,状态变为fulfilled
this.PromiseState = 'fulfilled'
// 终值为传进来的值
this.PromiseResult = value
// 执行保存的成功回调
+ while (this.onFulfilledCallbacks.length) {
+ this.onFulfilledCallbacks.shift()(this.PromiseResult)
+ }
}
reject(reason) {
// state是不可变的
if (this.PromiseState !== 'pending') return
// 如果执行reject,状态变为rejected
this.PromiseState = 'rejected'
// 终值为传进来的reason
this.PromiseResult = reason
// 执行保存的失败回调
+ while (this.onRejectedCallbacks.length) {
+ this.onRejectedCallbacks.shift()(this.PromiseResult)
+ }
}
then(onFulfilled, onRejected) {
// 接收两个回调 onFulfilled, onRejected
// 参数校验,确保一定是函数
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
if (this.PromiseState === 'fulfilled') {
// 如果当前为成功状态,执行第一个回调
onFulfilled(this.PromiseResult)
} else if (this.PromiseState === 'rejected') {
// 如果当前为失败状态,执行第二哥回调
onRejected(this.PromiseResult)
+ } else if (this.PromiseState === 'pending') {
+ // 如果状态为待定状态,暂时保存两个回调
+ this.onFulfilledCallbacks.push(onFulfilled.bind(this))
+ this.onRejectedCallbacks.push(onRejected.bind(this))
+ }
}
После добавления приведенного выше кода давайте посмотрим на эффект таймера:
const test2 = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('成功') // 1秒后输出 成功
// resolve('成功') // 1秒后输出 失败
}, 1000)
}).then(res => console.log(res), err => console.log(err))
3. Связанные вызовы
затем поддержите链式调用
, затем выполняется следующий受上一次then返回值的影响
, чтобы дать вам пример:
// 链式调用 输出 200
const p3 = new Promise((resolve, reject) => {
resolve(100)
}).then(res => 2 * res, err => console.log(err))
.then(res => console.log(res), err => console.log(err))
// 链式调用 输出300
const p4 = new Promise((resolve, reject) => {
resolve(100)
}).then(res => new Promise((resolve, reject) => resolve(3 * res)), err => console.log(err))
.then(res => console.log(res), err => console.log(err))
Из приведенного выше примера мы можем получить несколько точек знаний:
- 1. Сам метод then возвращает новый объект Promise
- 2. Если возвращаемое значение является объектом обещания, возвращаемое значение успешно, и новое обещание выполнено успешно.
- 3. Если возвращаемое значение является объектом-обещанием, возвращаемое значение — сбой, а новое обещание — сбой.
- 4. Если возвращаемое значение не является объектом-обещанием, новый объект-обещание считается успешным, и значением является это возвращаемое значение.
Мы знаем, что then — это метод в Promise, так как же реализовать then и then? Очень просто, затем возвращаетPromise对象
Вот и все, вы можете убедиться, что вы можете продолжить выполнение после этого:
Код:
then(onFulfilled, onRejected) {
// 接收两个回调 onFulfilled, onRejected
// 参数校验,确保一定是函数
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
var thenPromise = new MyPromise((resolve, reject) => {
const resolvePromise = cb => {
try {
const x = cb(this.PromiseResult)
if (x === thenPromise) {
// 不能返回自身哦
throw new Error('不能返回自身。。。')
}
if (x instanceof MyPromise) {
// 如果返回值是Promise
// 如果返回值是promise对象,返回值为成功,新promise就是成功
// 如果返回值是promise对象,返回值为失败,新promise就是失败
// 谁知道返回的promise是失败成功?只有then知道
x.then(resolve, reject)
} else {
// 非Promise就直接成功
resolve(x)
}
} catch (err) {
// 处理报错
reject(err)
throw new Error(err)
}
}
if (this.PromiseState === 'fulfilled') {
// 如果当前为成功状态,执行第一个回调
resolvePromise(onFulfilled)
} else if (this.PromiseState === 'rejected') {
// 如果当前为失败状态,执行第二个回调
resolvePromise(onRejected)
} else if (this.PromiseState === 'pending') {
// 如果状态为待定状态,暂时保存两个回调
// 如果状态为待定状态,暂时保存两个回调
this.onFulfilledCallbacks.push(resolvePromise.bind(this, onFulfilled))
this.onRejectedCallbacks.push(resolvePromise.bind(this, onRejected))
}
})
// 返回这个包装的Promise
return thenPromise
}
Теперь каждый может попробовать, как эффект, все хотятпостучи и попробуйОй:
const test3 = new MyPromise((resolve, reject) => {
resolve(100) // 输出 状态:成功 值: 200
// reject(100) // 输出 状态:失败 值:300
}).then(res => 2 * res, err => 3 * err)
.then(res => console.log('成功', res), err => console.log('失败', err))
const test4 = new MyPromise((resolve, reject) => {
resolve(100) // 输出 状态:失败 值:300
// reject(100) // 输出 状态:成功 值:200
// 这里可没搞反哦。真的搞懂了,就知道了为啥这里是反的
}).then(res => new MyPromise((resolve, reject) => reject(2 * res)), err => new MyPromise((resolve, reject) => resolve(3 * res)))
.then(res => console.log('成功', res), err => console.log('失败', err))
4. Микрозадачи
Видимыйjs执行机制
Братья знают, что тогда метод微任务
, Что такое микро задача? На самом деле, не имеет значения, если вы не знаете, я дам вам знать на следующем примере:
const p = new Promise((resolve, reject) => {
resolve(1)
}).then(res => console.log(res), err => console.log(err))
console.log(2)
输出顺序是 2 1
Почему не 1 2? Потому что это микрозадача. . . Точно так же мы должны добавить эту функцию в наш MyPromise (здесь я использую таймер, не обращайте на меня внимания)
просто позвольresolvePromise函数
Просто сделайте это асинхронно
const resolvePromise = cb => {
setTimeout(() => {
try {
const x = cb(this.PromiseResult)
if (x === thenPromise) {
// 不能返回自身哦
throw new Error('不能返回自身。。。')
}
if (x instanceof MyPromise) {
// 如果返回值是Promise
// 如果返回值是promise对象,返回值为成功,新promise就是成功
// 如果返回值是promise对象,返回值为失败,新promise就是失败
// 谁知道返回的promise是失败成功?只有then知道
x.then(resolve, reject)
} else {
// 非Promise就直接成功
resolve(x)
}
} catch (err) {
// 处理报错
reject(err)
throw new Error(err)
}
})
}
Взгляните на эффект:
const test4 = new MyPromise((resolve, reject) => {
resolve(1)
}).then(res => console.log(res), err => console.log(err))
console.log(2)
输出顺序 2 1
Другие методы
Эти методы относительно просты, я не буду говорить слишком много подробностей, мы также можем принять эту возможность, чтобы найти свой собственный путь, чтобы консолидировать знание этой статьи.
all
- Получить массив обещаний, если в массиве есть элемент, не являющийся обещанием, этот элемент считается успешным
- Если все обещания выполнены успешно, вернуть массив успешных результатов.
- Если обещание не выполняется, вернуть этот результат ошибки
static all(promises) {
const result = []
let count = 0
return new MyPromise((resolve, reject) => {
const addData = (index, value) => {
result[index] = value
count++
if (count === promises.length) resolve(result)
}
promises.forEach((promise, index) => {
if (promise instanceof MyPromise) {
promise.then(res => {
addData(index, res)
}, err => reject(err))
} else {
addData(index, promise)
}
})
})
}
race
- Получить массив обещаний, если в массиве есть элемент, не являющийся обещанием, этот элемент считается успешным
- Какой промис быстрее всего получает результат, возвращает этот результат, независимо от того, успешен он или нет
static race(promises) {
return new MyPromise((resolve, reject) => {
promises.forEach(promise => {
if (promise instanceof MyPromise) {
promise.then(res => {
resolve(res)
}, err => {
reject(err)
})
} else {
resolve(promise)
}
})
})
}
allSettled
- Получить массив обещаний, если в массиве есть элемент, не являющийся обещанием, этот элемент считается успешным
- Соберите результаты каждого промиса в массив и верните
static allSettled(promises) {
return new Promise((resolve, reject) => {
const res = []
let count = 0
const addData = (status, value, i) => {
res[i] = {
status,
value
}
count++
if (count === promises.length) {
resolve(res)
}
}
promises.forEach((promise, i) => {
if (promise instanceof MyPromise) {
promise.then(res => {
addData('fulfilled', res, i)
}, err => {
addData('rejected', err, i)
})
} else {
addData('fulfilled', promise, i)
}
})
})
}
any
любое противоположно всему
- Получить массив обещаний, если в массиве есть элемент, не являющийся обещанием, этот элемент считается успешным
- Если обещание выполнено успешно, вернуть этот результат успеха
- Если все обещания не выполняются, выдать ошибку
static any(promises) {
return new Promise((resolve, reject) => {
let count = 0
promises.forEach((promise) => {
promise.then(val => {
resolve(val)
}, err => {
count++
if (count === promises.length) {
reject(new AggregateError('All promises were rejected'))
}
})
})
})
}
}
Эпилог
Больше не боитесь, что интервьюер спросит у вас принцип Обещания хахахаха😁
Если вы считаете, что эта статья вам немного поможет, поставьте лайк и поддержите Линь Сансиня, ха-ха.
Если вы хотите изучать интерфейс или рыбачить вместе, вы можете добавить меня, присоединиться к моей группе по изучению рыбы, нажмите здесь. ---> коснуться точки кипения рыбы
Если у вас есть другие цели, не добавляйте меня, я не хочу с вами дружить, я просто хочу освоить фронтенд, я не хочу заниматься некоторыми вещами! ! !