标签:实现 pre cee 表达 instance 统计 出错 call script
同步回调:
理解: 立即执行, 完全执行完了才结束, 不会放入回调队列中
例子: 数组遍历相关的回调函数 / Promise的excutor函数
const arr = [1, 3, 5]
arr.forEach(item => { // 遍历回调, 同步回调函数, 不会放入列队, 一上来就要执行完
console.log(item)
})
console.log(‘forEach()之后‘)
异步回调:
理解: 不会立即执行, 会放入回调队列中将来执行
例子: 定时器回调 / ajax回调 / Promise的成功|失败的回调
Error:
所有错误的父类型ReferenceError:
引用的变量不存在TypeError:
数据类型不正确的错误RangeError:
数据值不在其所允许的范围内SyntaxError:
语法错误抽象表达:
Promise是 JS中进行异步编程的新的解决方案
具体表达:
从语法上来说: Promise是一个构造函数
从功能上来说:Promise对象用来封装一个异步操作并可以获取其结果
promise的状态改变(只有2种,只能改变一次)
pending 变为 resovled
pending 变为 rejected
resolve()
,或者reject()
,或者执行器抛出异常.then
的链式调用准备
(1)status
记录Promise
的状态,初始值为pendding
状态就是正在进行。
(2)data
记录Promise
返回的数据。
(3)callbacks
,这是一个数组,用来记录需要执行的回调函数队列,里面存储了成功和失败的回调。
(4) Promise
的参数为一个函数(构造器),函数里面又有两个函数调用,好了,了解清楚之后我们就可以开始写Promise
的结构了。
向外暴露Promise:
;(function (window) {
function Promise(executor){}
window.Promise = Promise
})(window)
构造器部分
既然构造器中有两个可执行函数,那么我们就要实现这两个函数。其实两个函数都是差不多的结构只是状态不同,执行的回调函数不同。那么实现我们上边说了,需要有三种状态,那么我们就需要进行定义,而且还需要定义执行的回调函数队列,并且需要有一个变量来存储存储返回的数据,那么思路捋清楚了就可以开始了:
/**
* @param {Function} executor 执行器
* @return {Promise} A new instance of Promise
* when catch error set promise.status to rejected
*/
function Promise(executor) {
const self = this
self.status = PENDING
self.data = null
self.callbacks = []
function resolve(value) {
// 状态只能改变一次
if (self.status !== PENDING) {
return
}
self.status = RESOLVED
self.data = value
if (self.callbacks.length > 0) {
setTimeout(() => {
self.callbacks.forEach((callbacksObj) => {
callbacksObj.onResolved(value)
})
})
}
}
function reject(reason) {
if (self.status !== PENDING) {
return
}
self.data = reason
self.status = REJECTED
if (self.callbacks.length > 0) {
setTimeout(() => {
self.callbacks.forEach((callbacksObj) => {
callbacksObj.onRejected(reason)
})
})
}
}
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
then
方法实现:
3.1
then
方法中也有两个回调函数,一个成功的回调,一个失败的回调,并且需要返回一个新的Promise
,这就是为什么Promise
可以链式调用的原因。写之前先捋一下逻辑,首先需要判断传入的是否为回调函数,如果为回调那么执行回调,如果成功回调为基本类型的值,那么次promise
就直接变为成功状态,若为失败那么直接向下抛出异常值。
then(onResolved, onRejected) {
onRejected = typeof === ‘function‘ ? onRejected : value => value // 否则拿到value值构造一个函数赋值给成功参数
onRejected = typeof === ‘function‘ ? onRejected : reason => { throw reason } // 否则变为一个向下抛出错误的异常函数
const self = this // 老样子保存引用
return new Promise((resolve, reject) => {
if(self.status === PENDING) { // pending状态我们将回调推入回调函数队列
self.callbacks.push({
OnResolved(value){}, // 回调里的操作决定了Promise的状态,所以还需要进行验证
onRejected(reason){}
})
}
} )
}
3.2
then方法第二部分(解决回调函数内容)
/*
返回promise的结果由onResolved/onRejected执行结果决定
1. 抛出异常, 返回promise的结果为失败, reason为异常
2. 返回的是promise, 返回promise的结果就是这个结果
3. 返回的不是promise, 返回promise为成功, value就是返回值
*/
所以我们需要一个 handler
函数来帮助我们判断回调函数的处理结果,之后才执行相应处理。
?
function handler(callback) {
/*
返回promise的结果由onResolved/onRejected执行结果决定
1. 抛出异常, 返回promise的结果为失败, reason为异常
2. 返回的是promise, 返回promise的结果就是这个结果
3. 返回的不是promise, 返回promise为成功, value就是返回值
*/
try {
const result = callback(self.data)
if (result instanceof Promise) {
result.then(resolve, reject)
} else {
resolve(result)
}
} catch (error) {
reject(error)
}
}
3.3
then方法第三部分(完善then)
Promise.prototype.then = function (onResolved, onRejected) {
const self = this
// 给参数赋予默认值,默认的函数
onResolved =
typeof onResolved === ‘function‘ ? onResolved : (value) => value
onRejected =
typeof onRejected === ‘function‘
? onRejected
: (reason) => {
throw reason
}
// 返回一个 promise
return new Promise((resolve, reject) => {
// 定义 handler函数,处理回调函数(利用闭包)
function handler(callback) {
/*
返回promise的结果由onResolved/onRejected执行结果决定
1. 抛出异常, 返回promise的结果为失败, reason为异常
2. 返回的是promise, 返回promise的结果就是这个结果
3. 返回的不是promise, 返回promise为成功, value就是返回值
*/
try {
const result = callback(self.data)
if (result instanceof Promise) {
result.then(resolve, reject)
} else {
resolve(result)
}
} catch (error) {
reject(error)
}
}
if (self.status === RESOLVED) {
// status 为 resolved 加入异步回调队列
setTimeout(() => {
handler(onResolved)
})
} else if (self.status === REJECTED) {
// status 为 rejected 加入异步回调队列
setTimeout(() => {
handler(onRejected)
})
} else {
// status 为 pending 装入回调数组
self.callbacks.push({
onResolved() {
// 改变状态
handler(onResolved)
},
onRejected() {
handler(onRejected)
},
})
}
})
}
catch
方法
catch
方法比较简单就是捕获错误,那么我们就可以直接复用then
方法。
Promise.prototype.catch = function (onRejected) {
return this.then(null, onRejected)
}
resolve
方法
返回一个 Promise对象,其实是一个语法糖
Promise.resolve = function (value) {
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then(resolve, reject)
} else {
resolve(value)
}
})
}
reject
方法
类似:
Promise.reject = function (reason) {
return new Promise((resolve, reject) => {
reject(reason)
})
}
all
和race
方法
all
方法接受一个数组,数组中的数据为Promise
多个实例,也可以是基本类型的值,当数组中的多个Promise
的状态全都成功时,这个返回值才是成功值,,否则失败。需要补充的是all
方法的成功返回值的顺序与数组中实例顺序是对应的关系。
race
方法的参数也是一个数组,数组中也是一个个promise
实例,但是这个方法返回的值并不是数组,而是哪个promise
率先执行完毕,那么此promise
的状态值就为这个promise
的状态值,听起来可能有点绕哈,下面开始代码的实现:
/**
* @param {[Promise]} promises The Array of promise
* @return {Promise} A new promise
*/
Promise.all = function (promises) {
const values = new Array(promises.length) // 保存结果
let resolvedCount = 0 // 统计resolved的Promise个数
return new Promise((resolve, reject) => {
promises.forEach((p, index) => {
Promise.resolve(p).then(
(value) => {
resolvedCount += 1
values[index] = value
if (resolvedCount === promises.length) {
resolve(values)
}
},
(reason) => {
reject(reason)
}
)
})
})
}
/**
* @param {[Promise]} promises The Array of promise
* @return {Promise} A new promise
*/
Promise.race = function (promises) {
return new Promise((resolve, reject) => {
promises.forEach((p) => {
Promise.resolve(p).then(
(value) => {
resolve(value)
},
(reason) => {
reject(reason)
}
)
})
})
}
标签:实现 pre cee 表达 instance 统计 出错 call script
原文地址:https://www.cnblogs.com/jiaweixie/p/13179720.html