基于队列的事件订阅和发布原理
class Promise {
constructor(fn) {
fn(this.resolve.bind(this));
}
callbacks = [];
state = 'pending';
value = null;
resolve(value) {
// 发布
this.state = 'fulfilled';
this.value = value;
this.callbacks.forEach(cb => cb(value));
}
then(callback) {
// 订阅
if (this.state === 'pending') {
this.callbacks.push(callback);
} else {
callback(this.value);
}
return this;
}
}
function promiseAll(list = []) {
return new Promise((resolve, reject) => {
var result = [];
for (var i = 0; i < list.length; i++) {
list[i].then(res => {
result.push(res);
if (result.length === list.length) {
resolve(result);
}
}).catch(rej => {
reject(rej);
});
}
})
}
let promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('定时器1')
}, 3000)
});
let promise2 = new Promise(resolve => {
setTimeout(() => {
resolve('定时器2')
}, 2000);
})
let promise3 = Promise.reject('err');
promiseAll([promise1, promise2]).then(res => console.log('res', res))
// res ["定时器1", "定时器2"]
promiseAll([promise1, promise2, promise3]).then(res => console.log('res', res))
// Promise {<rejected>: "err"}
function promiseRace(list) {
return new Promise((resove, reject) => {
list.forEach(promise => {
promise.then(resove, reject);
});
});
}
let promise1 = new Promise((resolve, reject) => {
setTimeout(() => resolve(100), 1000);
});
let promise2 = new Promise((resolve, reject) => {
setTimeout(() => resolve(200), 1500);
});
promiseRace([promise1, promise2]).then((res) => {
console.log(res);
});
Promise.prototype.finally = function(callback) {
var constructor = this.constructor;
return this.then(function(value) {
return constructor.resolve(callback()).then(function() {
return value;
});
}, function (reason) {
return constructor.resolve(callback()).then(function() {
throw reason;
});
})
}
Promise.resolve(1)
.then(2)
.then(Promise.resolve(3))
.then(console.log)
结果:
1
Promise.then()或 Promise.catch() 参数有两个特点:
- 类型默认是函数
- 有返回值
-
如果参数不是函数,则当前的
then
无法形成链式调用,相当于独立的promise
,不会对后续的promise
产生作用, 此时.then(2)
对后面的两个then不构成影响。 -
如果满足第一条,但函数没有返回值,此时
promise
无法将返回值传递个下一个then
。这里的then(Promise.resolve(3))
没有return
语句, 后面的then
也无法接受到值。 -
then
第一个函数抛出异常,第二个参数捕获不到,但catch
可以捕获到
promise
变成fulfilled
,如果在then
第一个参数中报错,第二个参数捕获不到,只有后面的catch
能捕获到。promise
变成rejected
,由于就近原则,then
的第二个参数就能捕获到。
const promise = new Promise((resolve, rejected) => {
throw new Error('test');
});
// 此时只有then的第二个参数可以捕获到错误信息
promise.then(res => {
//
}, err => {
console.log(err);
}).catch(err1 => {
console.log(err1);
});
// 此时只有then的第二个参数可以捕获到Promise内部抛出的错误信息
promise.then(res => {
throw new Error('hello');
}, err => {
console.log(err);
}).catch(err1 => {
console.log(err1);
});