promise
Объект Promise представляет собой асинхронную операцию с тремя состояниями: ожидание (выполняется), выполнено (успешно) и отклонено (сбой). После успеха нельзя допустить неудачи, после неудачи нельзя допустить успеха.
function Promise(excutor) {
let self = this
self.status = 'pending'
self.value = null
self.reason = null
function resolve(value) {
if (self.status === 'pending') {
self.value = value
self.status = 'fulfilled'
}
}
function reject(reason) {
if (self.status === 'pending') {
self.reason = reason
self.status = 'rejected'
}
}
try {
excutor(resolve, reject)
} catch (err) {
reject(err)
}
}
Промис получает функцию в качестве параметра, функция имеет два параметра, одинresolve
, указывающий функцию, которая будет выполнена в случае успеха, одинreject
, который представляет функцию, которая будет выполняться в случае сбоя.resolve
Параметры, переданные во время выполнения, будут использоваться какthen
Параметр первой функции обратного вызова в методе,reject
Выполнить входящие параметры какthen
Параметр обратного вызова второй функции в методе.
Promise.prototype.then = function (onFulfilled, onRejected) {
let self = this
if (self.status === 'fulfilled') {
onFulfilled(self.value)
}
if (self.status === 'rejected') {
onRejected(self.reason)
}
}
Некоторый асинхронный код часто пишется в Promise, который не будет запущен, пока асинхронная операция не будет завершена.resolve
илиreject
функция, при выполненииthen
Состояние в это время все еще остается начальным при использовании метода.pending
state, поэтому для получения параметров мы можем писать через режим публикации-подписки.
основной вызов
function Promise(excutor) {
let self = this
self.status = 'pending'
self.value = null
self.reason = null
self.onFulfilledCallbacks = []
self.onRejectedCallbacks = []
function resolve(value) {
if (self.status === 'pending') {
self.value = value
self.status = 'fulfilled'
self.onFulfilledCallbacks.forEach(item => item(self.value))
}
}
function reject(reason) {
if (self.status === 'pending') {
self.reason = reason
self.status = 'rejected'
self.onRejectedCallbacks.forEach(item => item(self.reason))
}
}
try {
excutor(resolve, reject)
} catch (err) {
reject(err)
}
}
Promise.prototype.then = function (onFulfilled, onRejected) {
let self = this
if (self.status === 'fulfilled') {
onFulfilled(self.value)
}
if (self.status === 'rejected') {
onRejected(self.reason)
}
if (self.status === 'pending') {
self.onFulfilledCallbacks.push(onFulfilled)
self.onRejectedCallbacks.push(onRejected)
}
}
Все мы знаем, что у Promise есть фича, то есть цепочка вызовов, при выполненииthen
Можно продолжить после завершенияthen
метод, по сути, его принцип реализуется за счет возврата нового промиса, затемthen
Код в методе можно записать следующим образом
Promise.prototype.then = function (onFulfilled, onRejected) {
let self = this
if (self.status === 'fulfilled') {
return new Promise((resolve, reject) => {
onFulfilled(self.value)
})
}
if (self.status === 'rejected') {
return new Promise((resolve, reject) => {
onRejected(self.reason)
})
}
if (self.status === 'pending') {
return new Promise((resolve, reject) => {
self.onFulfilledCallbacks.push(onFulfilled)
self.onRejectedCallbacks.push(onRejected)
})
}
}
then
В двух функциях, полученных методом, значение может быть передано на следующий шаг через return, или может быть возвращено новое обещание для передачи значения на следующий шаг.then
Есть особенность при выполнении метода, которая заключается в обеспечении цепного вызова, в последний разthen
В случае, если вы преуспевьте или потерпите неудачу, поставим параметры как следующийthen
Параметры обратного вызова в случае успеха, например
let promise1 = new Promise((resolve, reject) => {
reject('1')
})
let promise2 = promise1.then((res) => {
return 1
}, (err) => {
return 2
})
promise2.then((res) => {
console.log(res)//不管上一次then执行的那个回调函数,在这里都可以接收到参数
})
цепной вызов
Promise.prototype.then = function (onFulfilled, onRejected) {
let self = this
if (self.status === 'fulfilled') {
return new Promise((resolve, reject) => {
try {
let x = onFulfilled(self.value)
if (x instanceof Promise) {
x.then(resolve, reject)
} else {
resolve(x)
}
} catch (err) {
reject(err)
}
})
}
if (self.status === 'rejected') {
return new Promise((resolve, reject) => {
try {
let x = onRejected(self.reason)
if (x instanceof Promise) {
x.then(resolve, reject)
} else {
resolve(x)
}
} catch (err) {
reject(err)
}
})
}
if (self.status === 'pending') {
return new Promise((resolve, reject) => {
self.onFulfilledCallbacks.push(() => {
let x = onFulfilled(self.value)
if (x instanceof Promise) {
x.then(resolve, reject)
} else {
resolve(x)
}
})
self.onRejectedCallbacks.push(() => {
let x = onRejected(self.reason)
if (x instanceof Promise) {
x.then(resolve, reject)
} else {
resolve(x)
}
})
})
}
}
Обратите внимание, что независимо от того, является ли это обратным вызовом в случае успеха или обратным вызовом в случае неудачи, существуютtry/catch
Пакет, независимо от того, удачен он или нет, будет заменен следующим.resolve
Получено, будет выполнен только код ошибкиreject
, для обработки особых случаев,then
Нет функции обратного вызова в случае успеха или функции обратного вызова в случае неудачи, код сообщит об ошибке, поэтому укажите значение по умолчанию.
Promise.prototype.then = function (onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function (data) {return data}
onRejected = typeof onRejected === 'function' ? onRejected : function (err) {throw err}
let self = this
if (self.status === 'fulfilled') {
return new Promise((resolve, reject) => {
try {
let x = onFulfilled(self.value)
if (x instanceof Promise) {
x.then(resolve, reject)
} else {
resolve(x)
}
} catch (err) {
reject(err)
}
})
}
if (self.status === 'rejected') {
return new Promise((resolve, reject) => {
try {
let x = onRejected(self.reason)
if (x instanceof Promise) {
x.then(resolve, reject)
} else {
resolve(x)
}
} catch (err) {
reject(err)
}
})
}
if (self.status === 'pending') {
return new Promise((resolve, reject) => {
self.onFulfilledCallbacks.push(() => {
let x = onFulfilled(self.value)
if (x instanceof Promise) {
x.then(resolve, reject)
} else {
resolve(x)
}
})
self.onRejectedCallbacks.push(() => {
let x = onRejected(self.reason)
if (x instanceof Promise) {
x.then(resolve, reject)
} else {
resolve(x)
}
})
})
}
}
Стоит обратить внимание на указание по умолчанию, при сбое он будет продолжать выдавать ошибки, потому что только код сообщит об ошибке.reject
функция
метод ловли
фактическиcatch
Путь этоthen
сокращение для метода
Promise.prototype.catch = function (fn) {
return this.then(null, fn)
}
полный код
function Promise(excutor) {
let self = this
self.status = 'pending'
self.value = null
self.reason = null
self.onFulfilledCallbacks = []
self.onRejectedCallbacks = []
function resolve(value) {
if (self.status === 'pending') {
self.value = value
self.status = 'fulfilled'
self.onFulfilledCallbacks.forEach(item => item())
}
}
function reject(reason) {
if (self.status === 'pending') {
self.reason = reason
self.status = 'rejected'
self.onRejectedCallbacks.forEach(item => item())
}
}
try {
excutor(resolve, reject)
} catch (err) {
reject(err)
}
}
Promise.prototype.then = function (onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function (data) {resolve(data)}
onRejected = typeof onRejected === 'function' ? onRejected : function (err) {throw err}
let self = this
if (self.status === 'fulfilled') {
return new Promise((resolve, reject) => {
try {
let x = onFulfilled(self.value)
if (x instanceof Promise) {
x.then(resolve, reject)
} else {
resolve(x)
}
} catch (err) {
reject(err)
}
})
}
if (self.status === 'rejected') {
return new Promise((resolve, reject) => {
try {
let x = onRejected(self.reason)
if (x instanceof Promise) {
x.then(resolve, reject)
} else {
resolve(x)
}
} catch (err) {
reject(err)
}
})
}
if (self.status === 'pending') {
return new Promise((resolve, reject) => {
self.onFulfilledCallbacks.push(() => {
let x = onFulfilled(self.value)
if (x instanceof Promise) {
x.then(resolve, reject)
} else {
resolve(x)
}
})
self.onRejectedCallbacks.push(() => {
let x = onRejected(self.reason)
if (x instanceof Promise) {
x.then(resolve, reject)
} else {
resolve(x)
}
})
})
}
}
Promise.prototype.catch = function (fn) {
return this.then(null, fn)
}