- 滚动事件回调太频繁的问题
已知一个分页加载的卡券列表页,只要页面滚动到底部就向服务器发起请求,加载下一页卡券数据。
由于滚动事件非常频繁,过多的请求导致服务器压力很大。
请编写一个函数,减少上述场景发起请求的频率
/**
1. @param {Function} handler 逻辑函数
2. @param {number} gap 间隔时间(毫秒)
3. @returns {Function} 包裹函数
*/
const limit = (handler, gap = 100) => {
// code here
};
// Test codes, ignore.
Page({
onScoll: limit(function(e) {
// load next page
}, 100),
});
//答案:
const limit = (handler, gap = 100) => {
// code here
let timer = null
return function () {
let context = this,
args = arguments
// 如果此时存在定时器的话,则取消之前的定时器重新记时
if (timer) {
clearTimeout(timer)
timer = null
}
// 设置定时器,使事件间隔指定事件后执行
timer = setTimeout(() => {
handler.apply(context, args)
}, gap)
}
}
- 计算微信运动步数
已知小明2020-08-16至2020-09-15的微信运动步数数据如下:
// steps[].timestamp 数据采集的时间戳,单位毫秒
// steps[].step 距离上次采集后增加的步数
const steps = [
{ step: 1753, timestamp: 1597507200000 },
{ step: 1637, timestamp: 1597593600000 },
{ step: 6216, timestamp: 1597680000000 },
{ step: 6466, timestamp: 1597766400000 },
{ step: 12998, timestamp: 1597852800000 },
{ step: 7731, timestamp: 1597939200000 },
{ step: 7115, timestamp: 1598025600000 },
{ step: 3603, timestamp: 1598112000000 },
{ step: 1659, timestamp: 1598198400000 },
{ step: 3582, timestamp: 1598284800000 },
{ step: 6979, timestamp: 1598371200000 },
{ step: 4567, timestamp: 1598457600000 },
{ step: 7639, timestamp: 1598544000000 },
{ step: 9150, timestamp: 1598630400000 },
{ step: 8565, timestamp: 1598716800000 },
{ step: 6544, timestamp: 1598803200000 },
{ step: 6316, timestamp: 1598889600000 },
{ step: 15523, timestamp: 1598976000000 },
{ step: 8254, timestamp: 1599062400000 },
{ step: 13552, timestamp: 1599148800000 },
{ step: 6163, timestamp: 1599235200000 },
{ step: 6338, timestamp: 1599321600000 },
{ step: 8508, timestamp: 1599408000000 },
{ step: 4002, timestamp: 1599494400000 },
{ step: 7501, timestamp: 1599580800000 },
{ step: 5922, timestamp: 1599667200000 },
{ step: 9635, timestamp: 1599753600000 },
{ step: 7067, timestamp: 1599840000000 },
{ step: 3878, timestamp: 1599926400000 },
{ step: 4088, timestamp: 1600012800000 },
{ step: 773, timestamp: 1600099200000 }
]
请编写一个函数,将其中某个时间段的步数进行小计,返回小计结果
示例:
输入:2020-09-01, 2020-09-07
返回:64654
const calcSteps = (
steps: { step: number, timestamp: number }[],
startDate: string = '2000-01-01',
endDate: string = '3000-01-01',
): number => {
// code here
};
答案:
//答案:
const calcSteps = (startDate, endDate)=> {
// code here
const newSteps = steps.filter(item => item.timestamp >= new Date(new Date(startDate).toLocaleDateString()).getTime() && item.timestamp <= new Date(endDate).getTime())
const num = newSteps.reduce((sum, item) => sum + item.step, 0)
return num
};
console.log(calcSteps('2020-09-01', '2020-09-07'))
- 观察者模式
请根据以下类型定义,补充实现观察者模式的代码:
/**
* 订阅者
* @property {() => void} remove 取消订阅
*/
type Listener = {
remove: () => void;
};
/**
* 回调 callback
*/
type Callback = {
(data: unknown): unknown;
};
interface EventSupport {
/**
* 订阅事件
* @param event 事件名
* @param callback 订阅函数
* @returns {Listener}
*/
on(event: string, callback: Callback): Listener;
/**
* 取消订阅
* @param event 事件名
* @param callback 订阅函数
*/
off(event: string, callback?: Callback): void;
/**
* 触发事件
* @param event 事件名
* @param data 数据
*/
emit(event: string, data:unknown): void;
}
class MyEvent implements EventSupport {
// code here
}
// 测试代码
const myEvent = new MyEvent();
const listener1 = myEvent.on('event1', (param) => {
console.log('event1 emitted with', param);
});
const callback2 = (param: any) => {
console.log('event2 emitted with', param);
};
myEvent.on('event2', callback2);
myEvent.emit('event1', '1.1'); // 输出 'event1 emitted with 1.1'
myEvent.emit('event1', '1.2'); // 输出 'event1 emitted with 1.2'
listener1.remove();
myEvent.emit('event1', '1.3'); // <nothing happened>
myEvent.emit('event2', '2.1'); // 输出 'event2 emitted with 2.1'
myEvent.off('event2', callback2);
myEvent.emit('event2', '2.2'); // <nothing happened>
答案:
class MyEvent {
constructor() {
this._events = new Map() //存储发布者和订阅者
}
on(type, fn) {
//发布和订阅
//获取到该发布者下的订阅者集合handler
let handler = this._events.get(type)
//如果还没有订阅者
if (!handler) {
this._events.set(type, [fn]) //加入这个订阅者
} else {
handler.push(fn) //直接push进去handler
}
return myEvent
}
emit(type, ...args) {
//执行该订阅下的所有函数
let handler = this._events.get(type)
for (let i = 0; i < handler.length; i++) {
handler[i].apply(this, args) //执行第i个订阅者函数
}
if (handler.length < 1) {
console.log('<nothing happened>')
}
}
off(type, fn) {
//取消某个函数的订阅
let handler = this._events.get(type) //获取所有的订阅者
//数组中订阅者有多个,找到等于fn的订阅者删除
handler.splice(
handler.findIndex((e) => e === fn),
1
)
}
remove() {
// console.log(this._events.get())
// this._events.clear()
console.log('<nothing happened>')
}
}