/**
* promise的一些操作
*/
/**
* promise是一种异步编程解决方案,通俗说就是一个存放未来才会结束的事件的容器
* promise有三种状态
* 1.fulfilled:执行成功返回状态
* 2.pending:正在执行中的状态,也有说是初始状态,既不是成功,也不是失败
* 3.rejected:执行失败返回的状态
* 状态一旦发生改变就不会再变,比如由pending->rejected或者由pending->到fulfilled,就会一直保持失败或者成功的状态,无法改变
* Promise实例有两个方法,catch和then
* then可以链式调用,catch可以捕捉多个promise中抛出的错误,但是抛出错误的后续的promise不再执行了
* node中有专门捕捉未监听的reject错误事件:unhandledRejection
* process.on('unhandledRejection',function(err,p){
* console.error(err.stack)
* })
*/
/**
* promise.then属于微任务,在宏任务执行完成后才会执行
* 执行过程:
* 1.console.log('start')被执行,输出'start'
* 2.async1执行,加入microtask队列
* 3.setTimeout执行,加入macrotask队列
* 4.promise1执行,他的两个then加入microtask队列
* 5.console.log('end')被执行,输出'end'
* 6.按照事件循环的定义,接下来会执行新增的microtask任务,再执行加macrotask任务,所以第一次事件循环
* 的输出结果为:start,async2,promise,end,这时候microtask队列为空,执行下一轮循环,从macrotask
* 队列里取位于队首的任务(async1)并执行,输出async1,以此类推
*/
console.log('start')
async function async1() {
await async2()
console.log('async1')
}
async function async2() {
console.log('async2')
}
async1()
setTimeout(function () {
console.log('setTimeout')
}, 0)
new Promise(resolve => {
console.log('promise1')
resolve()
}).then(() => {
console.log('promise2')
}).then(() => {
console.log('promise3')
})
console.log('end')
/**
* new Promise((reslove,reject)=>{}):返回一个Promise对象
* Promise.all():将多个Promise实例包装成一个新的Promise实例,参数不一定是数组,但一定具有iterable接口,
* 所有的Promise都成功才触发成功,若一个失败则失败
* Promise.race():跟参数和all()方法一样,iterable参数中的一个成功或者失败都会立即触发返回对象的成功和失败
* 比如:实现如下调用,lazyMan('xxx').sleep(1000).eat('333').sleepFirst(2000) sleepFirst最先执行。
*/
function lazyMan(name) {
this.task = []
this.task.push(() => {
return new Promise(resolve => {
console.log('name:', name);
resolve()
})
})
//将事件形成链式调用
let run = () => {
let sequence = Promise.resolve()
for (let func of this.task) {
sequence = sequence.then(() => func())
}
}
//根据事件循环,通过定时器将事件链式调用
setTimeout(() => {
run()
}, 0)
this.sleep = (time) => {
this.task.push(() => {
return new Promise(resolve => {
setTimeout(() => {
console.log('sleep:', time);
resolve()
}, time)
})
})
return this
}
this.eat = (str) => {
this.task.push(() => {
return new Promise(resolve => {
console.log('eat:', str);
resolve()
})
})
return this
}
//将sleepFirst推到任务队列的第一个
this.sleepFirst = (time) => {
this.task.unshift(() => {
return new Promise((resolve) => {
setTimeout(() => {
console.log('sleepFirst:', time);
resolve()
}, time)
})
})
return this
}
return this
}
lazyMan('xxx').sleep(300).eat('333').sleepFirst(200)
/**
* 任务队列可不断的添加异步任务(异步任务都是Promise),但只能同时处理5个任务,
* 5个一组执行完成后才能执行下一组,任务队列为空时暂停执行,当有新任务加入则自动执行。
*/
class RunQune {
constructor() {
this.list = [] //任务队列数组
this.targe = 5 //并发数量
this.flag = false //任务执行状态
this.date = Date.now()
}
//模拟任务执行等待时间
static async sleep(time) {
return new Promise(resolve => {
setTimeout(resolve, time)
})
}
static async run() {
while (this.list.length > 0) {
this.flag = true
let runList = list.slice(0, this.targe)
this.date = Date.now()
await this.runItem(runList)
await this.sleep(1000)
}
this.flag = false
}
static async runItem(list) {
return new Promise(resolve => {
while (list.length > 0) {
const fn = list.shift()
fn().then().finally(() => {
if (list.length === 0) {
resolve()
}
})
}
})
}
//加入任务
static push(task) {
this.list.push(...task);
!this.flag && this.run()
}
}
/**
* 手动实现一个promise
*/
function MyPromise(executor) {
this.status = 'pending' // pending , fulfilled , rejected
this.data = '' // 当前promise的值,主要用于 then 方法中的 fulfilled , rejected 两种状态的处理
this.resolveFuncList = [] // 使用数组的原因是,一个promise可以同时执行多个 then 方法, 也就会同时存在多个then回调
this.rejectFunc;
let self = this
function resolve(value) {
setTimeout(() => {
if (self.status === 'pending') {
self.status = 'fulfilled'
self.data = value
self.resolveFuncList.forEach(func => {
func(value)
})
}
})
}
function reject(reason) {
setTimeout(() => {
if (self.status === 'pending') {
self.status = 'rejected'
self.data = value
self.rejectFunc && self.rejectFunc(reason)
}
})
}
try {
executor(resolve, reject)
} catch (e) {
reject(e)
}
}
function resolvePromise(promise2, val, resolve, reject) {
if (val instanceof MyPromise) {
if (val.status === 'pending') {
val.then(value => {
resolvePromise(promise2, value, resolve, reject)
}, reason => {
reject(reason)
})
} else {
val.then(resolve, reject)
}
} else {
resolve(val)
}
}
MyPromise.prototype.then = function (onFulfilled, onRejected) {
let promise2
if (this.status === 'pending') {
return promise2 = new MyPromise((res, rej) => {
this.resolveFuncList.push(function (value) {
let val = onFulfilled(value) //输出将上一次执行结果
resolvePromise(promise2, val, res, rej)
})
this.rejectFunc = function (reason) {
let val = onRejected(reason)
resolvePromise(promise2, val, res, rej)
}
})
}
if (this.status === 'fulfilled') {
return promise2 = new MyPromise((res, rej) => {
setTimeout(() => {
let val = onFulfilled(this.data)
resolvePromise(promise2, val, res, rej)
})
})
}
if (this.status === 'rejected') {
return promise2 = new Promise((res, rej) => {
setTimeout(() => {
let val = onRejected(this.data)
resolvePromise(promise2, val, res, rej)
})
})
}
}
async function test() {
return new MyPromise((resolve, reject) => {
resolve('ceshi')
})
}
async function test1() {
await test().then(r => {
console.log(r)
})
}
test1()
/**
* 实现promise.all()
*/
Promise.all = function (promises) {
return new Promise((resolve, reject) => {
let values = []
let count = 0
promises.forEach((promise, index) => {
promise.then(value => {
values[index] = value
count++
if (count === promises.length) {
resolve(values)
}
}, reject)
})
})
}
/**
* 实现promsie.race()
*/
Promise.race = function (promises) {
return new Promise((resolve, reject) => {
promises.forEach((promise, index) => {
promise.then(resolve, reject)
})
})
}
promise的学习记录
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- JavaScript Promise 学习记录(一) 本文首先介绍了promise的三种状态及生成不同状态prom...
- 成长记录-连载(三十六) ——我的第一篇五千字长文,说了什么,你一定想不到 并不是不想每天写公众号,而是之前思考怎...
- 教练式提问 关于对孩子教育的投资,你是如何看待? 对于现今社会,孩子的宝贝程度不亚于总统,坊间有关于小孩的培训机构...
- 2020年3月22日星期日 通辽心协心理援助学习营成长记录 方舟援助学习营--学习的摇篮 2020年春天,是注定要...