1. 滚动事件回调太频繁的问题/2. 计算微信运动步数/3. 观察者模式

  1. 滚动事件回调太频繁的问题

已知一个分页加载的卡券列表页,只要页面滚动到底部就向服务器发起请求,加载下一页卡券数据。

由于滚动事件非常频繁,过多的请求导致服务器压力很大。

请编写一个函数,减少上述场景发起请求的频率

/**
 * @param {Function} handler 逻辑函数
 * @param {number} gap 间隔时间(毫秒)
 * @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)
  }
}
  1. 计算微信运动步数

已知小明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'))

3.观察者模式

请根据以下类型定义,补充实现观察者模式的代码:

/**
  * 订阅者
  * @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>')
  }
}

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值