并发控制
class Concurrent {
constructor(limit) {
this.limit = limit
this.running = 0
this.queue = []
}
run (fn, ...args) {
return new Promise((resolve, reject) => {
const task = () => {
this.running++
fn(...args).then(resolve).catch(reject).finally(() => {
this.running--
if (this.queue.length) {
this.queue.shift()()
}
})
}
if (this.running < this.limit) {
task()
} else {
this.queue.push(task)
}
})
}
}
const concurrent = new Concurrent(3)
const p = (t) => {
console.log('开始运行', t)
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('结束', t)
resolve(t)
}, t)
})
}
Promise.all([
concurrent.run(p, 4000),
concurrent.run(p, 401),
concurrent.run(p, 500),
concurrent.run(p, 501),
concurrent.run(p, 502),
concurrent.run(p, 503),
concurrent.run(p, 504),
concurrent.run(p, 505),
])
.then((res) => {
console.log(res, 'done')
})
.catch((error) => {
console.error('Error:', error)
})
// 开始运行 4000
// 开始运行 401
// 开始运行 500
// 结束 401
// 开始运行 501
// 结束 500
// 开始运行 502
// 结束 501
// 开始运行 503
// 结束 502
// 开始运行 504
// 结束 503
// 开始运行 505
// 结束 504
// 结束 505
// 结束 4000
// [4000, 401, 500,501, 502, 503,504, 505] done
call和apply方法
call,apply是用于绑定this指向的,他们就是参数不同,作用基本相同。
- 每个函数都包含两个非继承而来的方法:
apply()和call()。 - 他们的用途相同,都是在特定的作用域中调用函数。
- 接收参数方面不同,
apply()接收两个参数,一个是函数运行的作用域(this),另一个是参数数组。 call()方法第一个参数与apply()方法相同,但传递给函数的参数必须列举出来。
手写Bind
function fn1(a,b,c) {
console.log("this", this, "参数", a, b, c);
return "this fn1"
}
// 原生bind
const fn2 = fn1.bind({t: "指定的this"})
fn2(1,2,3) // 输出: this { t: '指定的this' } 参数 1 2 3
// 手动实现的bind
Function.prototype.bind2 = function (context) {
context = typeof context === "object" ? (context || widnow) : window
return (...args) => {
this.call(context, ...args)
}
}
const fn3 = fn1.bind2({t: "指定的this - 3"})
fn3(2,2,4) // 输出: this { t: '指定的this - 3' } 参数 2 2 4
手写call
function f1(a, v) {
console.log("this", this, "参数", a, v);
}
Function.prototype.call2 = function (context) {
context = typeof context === "object" ? (context || widnow) : window
const args = arguments[1] //获取传入的数组参数
const key = Symbol()
context[key] = this
const res = context[key](...arg)
delete context[key]
return res
}
const context = {t: "指定的this - call"}
f1.call2(context, 1,2)
console.log(context);
/* 输出
this { t: '指定的this - call', fn: [Function: f1] } 参数 1 2
{ t: '指定的this - call' }
*/
实现new
function Man(options) {
this.age = options.age
this.name = options.name
Man.prototype.work = "nonw"
}
// 原生 new
const m = new Man({name: "原生new", age: 0})
// 手写new
function myNew (context, ...args) {
const obj = {}
obj.__proto__ = context.prototype
context.call(obj, ...args)
return obj
}
const s = myNew(Man, {name: "my new", age: 1})
console.log(m, s);
// 输出 Man { age: 0, name: '原生new' } Man { age: 1, name: 'my new' }
Event Bus
class EventBus {
constructor() {
this.map = {}
}
on(type, fn) {
this.map[type] = (this.map[type] || []).concat(fn)
}
emit(type, ...args) {
if (this.map[type]) {
this.map[type].forEach(f => {
f(...args)
});
}
}
off(type, fn) {
if (this.map[type]) {
if (fn) {
const index = this.map[type].indexOf(fn)
index > -1 && this.map[type].splice(index, 1)
} else {
delete this.map[type]
}
}
}
}
发布、订阅
class Subject {
constructor() {
this.observes = []
}
addObserves(observe) {
this.observes.push(observe)
}
delObserve(observe) {
const index = this.observes.indexOf(observe)
index > -1 && this.observes.splice(index, 1)
}
update() {
this.observes.forEach(o => {
o.update()
})
}
}
class Observe {
update() {
// do something
}
subscribeTo(subject) {
subject.addObserves(this)
}
}