「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」
本章主要带大家学习Promise的相关知识点,希望能通过本章来彻底掌握js世界中Promise相关知识
高阶函数
一个函数可以接受一个参数是函数,或者一个函数返回一个函数,我门称这个函数为高阶函数。 高阶函数的作用有哪些呢?
- 扩展函数的功能
function say(args) { // 我们需要对say方法进行扩展,但是不能修改源代码
console.log('say', args)
}
Function.prototype.before = function (cb) {
return (...args) => { // newSay
cb();
this(...args); // 扩展原来的函数
}
}
let newSay = say.before(() => {
console.log('beforeSay')
})
newSay('hello');
- 保留参数变量
function isType(typing) {
return (val) => {
return Object.prototype.toString.call(val) === `[object ${typing}]`
}
}
// 利用高阶函数保留参数变量
let isString = isType('String');
console.log(isString('hello'));// true
console.log(isString(123)); // false
异步处理
前端常见的就是 同时发送多个请求,最终拿到多个请求的返回值 来进行渲染页面,下面会介绍几种方法
这里创建两个文件用来模拟异步的请求数据name.txt, age.txt;内容分别为小明,18
回调函数
通过回调函数来处理异步加载操作,当所有的异步请求都完成后打印data
const fs = require('fs')
const path = require('path')
const fn = function(timer, callback){
const obj = {}
return (k,v)=>{
obj[k] = v
if (--timer === 0){ // 这里保留了参数
callback(obj)
}
}
}
const done = fn(2, (data) => {
console.log('data',data) // {name: '小明',age: '18'}
})
fs.readFile(path.resolve(__dirname, 'name.txt'), 'utf8', (err, data)=>{
done('name', data)
})
fs.readFile(path.resolve(__dirname, 'age.txt'), 'utf8', (err, data)=>{
done('age', data)
})
发布订阅模式
上面的代码有点杂乱,不是很易读,下面利用发布订阅模式来处理
const fs = require('fs')
const path = require('path')
// 发布订阅模式
let event = {
_events: [], // 存放事件,发布的时候执行
on(fn){
this._events.push(fn) // 订阅
},
emit(...age){
this._events.forEach(fn => {
fn(...age)
})
}
}
let obj = {}
event.on((k,v)=>{ // 订阅
obj[k] = v
if (Object.keys(obj).length === 2){
console.log('---', obj)
}
})
fs.readFile(path.resolve(__dirname, 'name.txt'), 'utf8', (err, data)=>{
event.emit('name', data) // 读取完数据发布消息
})
fs.readFile(path.resolve(__dirname, 'age.txt'), 'utf8', (err, data)=>{
event.emit('age', data) // 读取完数据发布消息
})
当读完一个文件后,发布消息,执行赋值操作,这样看起来清晰很多。
观察者模式
观察者模式包含发布订阅模式,不同点在于发布订阅模式中发布和订阅是没有耦合关系的,发布时间取决于自己,而在观察者模式中被观察者需要收集观察者,当被观察者状态改变时来主动通知观察者。
class Subject {
constructor(name){
this.name = name
this.event = []
this.status = ''
}
changeStatus(val){
this.status = val
this.event.forEach(item => {
item.updata(this) // 主动通知更新
})
}
add(o){
this.event.push(o)
}
}
class Observer{
constructor(name){
this.name = name
}
updata(bb){
console.log(this.name,':观察到小宝宝', bb.name, bb.status)
}
}
let ff = new Observer('ff')
let mm = new Observer('mm')
let bb = new Subject('bb')
bb.add(f) // 被观察者收集观察者
bb.add(mm) // 被观察者收集观察者
setTimeout(() => {
bb.changeStatus('哭')
// ff :观察到小宝宝 bb 哭
// mm :观察到小宝宝 bb 哭
}, 3000);
Promise-简单的同步版
在有上面的基础下,可以实现一个简单的同步版promise;首先了解promise有哪些东西。
- Promise是一个类,通过
new来创建,实例上有一个then方法 - promise有三种不可转换状态,
PENDINGREJECTEDFULFILLED - promise传入一个立即执行函数
executor - promise有一个成功的数据
value和一个失败原因reason - promise中出现异常会执行失败的逻辑 下面根据上面的条件生成一个自己的Promise
const PENDING = 'PENDING'; // 三种状态
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
class Promise {
constructor(executor){
this.value = undefined // 成功原因
this.reason = undefined // 失败原因
this.state = PENDING // 状态
const resovle = (value)=>{ // 改变状态方法
this.value = value // 存储成功值
this.state = FULFILLED // 改变状态
}
const reject = (value)=>{
this.reason = value // 存储失败原因
this.state = REJECTED // 改变状态
}
try{ // 处理异常,若异常走失败处理逻辑
executor(resovle, reject) // 立即执行函数执行
}catch(err){
reject(err)
}
}
then(suc, rej){
if (this.state === FULFILLED){ // 判断状态-成功,执行suc函数并把成功值传递
suc(this.value)
}
if (this.state === REJECTED){ // 判断状态-失败,执行rej函数并把失败原因传递
rej(this.reason)
}
}
}
let a = new Promise((resovle, rej)=>{
console.log('---')
// throw new Error('0000')
// resovle('成功')
rej('失败')
})
a.then((res)=>{
console.log('res', res) // resovle('成功') : ‘成功’
},(rej)=>{
console.log(' rej', rej) // ‘失败’
// throw new Error('0000') : '00000'
})
这样就实现了一个最简单的promise,现在实现的promise可以.then,可以判断成功失败进行不同处理,但是不能进行异步的处理,因为这个promise中没有处理异步逻辑,在then中会一直认为是等待状态,下一篇会处理异步,链式调用等问题。