祈福,在线教育ESLive直播的时刻事件队列怎么完成?技能大牛在线辅导!,凌潇肃

admin 2个月前 ( 05-03 01:35 ) 0条评论
摘要: 在线教育ESLive直播的时间事件队列如何实现?技术大牛在线指导!...

前语

内容导览

一、规划初

事务需求:在详细事务中能够独自建立既定时刻,要求 在该时刻内履行相应的操作,一起确保操作的精准度。

功用点剖析

三个要点考虑要素

1. 在播映的时刻轴中,工作是按时刻次序顺次履行

经过规划对应的数据结构,保存顺次履行的点的 时刻数据 男同video和 详细办法内容,来保证顺次履行。

// time: function(){} => 时刻点: 办法,这种数据格局可米菲哭了以一起保存时刻和办法。

let List = {

event: {

1: () => console.log(1),

2: () => console.log(2),

3: () => console.log(3)

}

};

list.event[time](); // 履行特定时刻的办法只需 如此

2. 当时播映时刻点和工作增加时刻点的差错

2.1 首要咱们需求区别如下两个概念

2.2 两者在很大概率上不一致,详细原因如下:

1 video 标签和 flash 形成的推迟

2 直播过程中的骚操作导致的推迟

2.3 处理思路 —— 挑选出小于等于当时时刻点的一切时刻

目标的方式遍历起来比较费事,所以需求别的一个参照物去取一个契合条件的时刻点的调集。so,感觉一个数据结构现已无法满意这个需求了。

let List = {

time: [1,漂泊记吉他谱 2, 3], // 播映的时刻轴

event: {

1: () => console.log(1),

2: () => console.log(2),

3: () => console.log(3)

}

};

引进 setList 办法

以上数据格局的关键在于 time 这个数据有必要始终坚持有序状况,即在注册工作的时分就 有必要让 time 的数据坚持有序。为了便利后续获取契合条件的时刻区间,咱们界说了一个 setList 办法回来当时数据地点的下标。

setList(list, value) {

if (isArray(list)) {

if (!list.length) {

list.push(value);

return 1;

}

for (var i = 0; i < list.length; i++) {

if (list[i] > value) {

list.splice(i, 0, value);

return i + 1;

} else if (i == list.length - 1) {

list.push(value);

return i + 1;

}

}

}

}

// 相应的触发也需求作出恰当调整(篇幅较长)

getTimeIndex(time) {

// 为了不让视频时刻污染原有的时刻点,这儿选用深复制进行了处理。感觉上能够修正setList避开这儿的深复制

let timeCurrentList = Compute.cloneObj(this.timeList);

let eventIndex = Compute.setList(timeCurrentList, time);

if (eventIndex >= 0) {

return {

index: eventIndex,

list: timeCurrentList.slice(0, eventIndex)

};

}

return {

index: -1,

list: []

}

}

triggerByLimit(time) {

let currentTrigger = getTimeIndex(time);

if (!currentTrigger.index) {

return;

}

list.time.map((value) => {

triggerByTime(value);

})

}

// 时刻点触发 工作

triggerByTime(time) {

if(this.list.event[time]) {

this.list.event[time]();

}

}

// 在这儿就衍生出一个细节,已履行的办法不应该屡次履行,这儿需求抛出已履行的办法。

removeFromList(list, va齐思乔lue) {

if (this.isArray(list)) {

if (list.indexOf(value) >= 0) {

list.splice(list.indexOf(value), 1);

return list;

}

}

}

// 履行完办法后需求做抛出操作

delete list.event[time];

removeFromList(list.time, time);

3. 当获取精准度较低时,或许呈现同一个时刻点注册多个办法的状况

当同一个时刻点注册多个办法时,会顺次衍生出两个小问题电动直立床。

问题1 相一起刻点下多个工作的掩盖

运用本来 目标 的方式,会导致后加的工作会把前者掩盖,无法完结多个工作的增加。所以咱们凭借 数组 进行了恰当的调整。

// 这样就能记载同一个时刻点的多个办法

let List = {

time: [1, 2, 3],

event: {

1: [

() => console.log(1-1),

() => console.log(1-2)

],

2: [

() => console.log(2)

],

3: [

() => console.log(3-1),

() => console.log(3-2),

() => console.log(3-3),

]

}

};

问题2 屡次 录入相一起刻点的工作

在 time 列表增加时,遇到相一起刻点的工作其实没有必要屡次录入,所以对 setList 进行了纤细调整。

setList(list, value) {

if (this.isArray(list)) {

if (list.indexOf(value) >= 0) {

return list.indexOf(value) + 1;

}

if (!list.length) {

list.push(value);

return 1;

}

for (var i = 0; i < list.length; i++) {

if (list[i] > value) {

lis祈福,在线教育ESLive直播的时刻工作行列怎样完结?技术大牛在线教导!,凌潇肃t.splice(i, 0, value);

return i + 1;

} else if (i == list.length - 1) {

list.push(value);

return i + 1;

}

}

} else {

return 0;

}

}

// 相应的,触发也要做出恰当修正,原先的this.list.event[time]();也要修正,抛出也要修正。。。。

this.eventList[time].map((value) =>香痰盂; {

value();

removeFromList(this.eventList[time], value);

if (!this.eventList[time].length) {

removeFromList(this.timeList, time);

delete this.eventList[time];

}

});

需求工作列表的格局 、注册行为开始成形

setTimeList(time) {

setList(this.list.time, time);

}

on(event) {

this.setTimeList(event.time);

if (!this.eventList[event.time]) {

this.eventList[event.time] = [event.callBack];

} else {

this.eventList[event.time].push(event.callBack);

}

}

二、精准度&回跳

推迟问题描绘

注册一个在 1.0s 履行的办法 ,比照一下 video标签 和 flash发生的推迟现象。

类型工作注册时刻点获取到的当时时刻点触发时刻推迟时刻video 标签1.0s0.9s, 1.5s1.5s0.5sfl肿瘤专家王振国ash1.0s0.7s, 3.5s3.5s2.5s

依照以上逻辑,工作别离是在 1.5s 和 3.5s 才被触发,别离推迟了 0.5s 和 2.5s。

优化计划

举个比如,当时时刻点为3s,设置稍长时刻为1s,那么当时时刻到稍长时刻这一区间为4s之前。

回跳 功用描绘

1 注册了一个 10.0s 履行的办法,实践上 video张境原坐月子 标签 ontimeupdate 时刻戳跑的时分获取到的当时时刻是 9.5s, 10.1s 的次序。

2 然后稍长时刻设定的 1s,这样工作在 9.5s 被注册进行列内。

3 接着用户操作在 9.8s 回跳至 3s,可是现已延时处理的内容并没有撤销。

4 导致终究本应该在 10s 呈现的办法在 3.2s 仍是照旧履行。

考虑到 这种状况,咱们需求在回跳办法中操作那些推迟处理的办法调集。这样就需求引进一个 等候执祈福,在线教育ESLive直播的时刻工作行列怎样完结?技术大牛在线教导!,凌潇肃行的工作行列 。

引进 等候履行的工作行列 waitingList

waitingList = {

// 同一个时刻点也会存在多个回跳工作。

1: [

() => console.log(1),

() => console.log藏密圣方(2)

]

}

class WaitingExecut {

constructor(options) {

this.callBack = options.callBack;

this.waitTime = options.waitTime;

this.init();

}

init() {

if (this.waitTime > 0) {

this.waiting = setTimeout(() => {

this.callBack();

this.doneFlag = true;

},this.waitTime);

祈福,在线教育ESLive直播的时刻工作行列怎样完结?技术大牛在线教导!,凌潇肃

} else {

this.callBack();

this.doneFlag = true;

}

}

// 履行

execut() {

if (!this.doneFlag) {

this.callBack();

clearTimeout(this.waiting);

this.doneFlag = true;

}

}

// 间断

abort() {

if (!this.doneFlag) {

clearTimeout(this.waiting);

this.doneFlag = true;

}

}

// 从头设定

reset() {

if (!this.doneFlag) {

clearTimeout(this.waiting);

}

this.doneFlag = false;

this.init();

}

// 重启

refresh(callBack, waitTime) {

this.abort();

this.callBack = callBack;

this.waitTime = waitTime;

this.init();

}

}

export default WaitingExecut;

这样就形成了 waiti丧命情网ngList 行列,继而能够较为便利地设置延时行为,例如撤销 abort、当即履行 e国王坛风云录xecut、重启 refresh、从头设定 reset 等等操作。

行列细节优化

1 引进 limit 概念

延时任务要呈现,就要有一个limit的概念。所以,挑选需求的工作要做恰当修正,挑选契合条件的时刻段能够稍善于当时时刻。

triggerByLimit(time, limit) {

// 要把需求的工作稍稍延伸,当然这个limit能够当作目标的固定特点,这儿或许依照实践获取的时刻距离为参照更好一些,所以只是当作参数办法运用。

let currentTrigger = this.getTimeIn官子萱dex(time + limit);

if(!currentTrigger.index) {

return;

}

currentTrigger.list.map((value, index, array) => {

// 这儿也需求把当时时刻给引进,便利做延时处理。

this.triggerByTime(value, time);

})

}

2 将 推迟处理的工作 参加到 waitingList 中

独自的某一点的触发也要恰当修正,不只是是要把当即履行和推迟处理参加,还有要把推迟处理的工作参加 waitingList。

triggerBy派券王Time(time, triggerTime) {

if(this.eventList[time]) {

this.eventList[time].map((value, index, array) => {

// 把推迟处理的工作参加到 waitingList 中

if (!this.waitingList[time]) {

this.waitingList[time] = [triggerItem];

} else {

this.waitingList[time].push(triggerItem);

}

let triggerItem = new陈子豪戳穿魄狙 WaitingExecut({

waitTime: time - triggerTime,

callBack: () => {

value();

// 下面这个办法作用是抛出 waitingList 内部的内容

this.clearTriggerItem(time, value);

}

});

Compute.removeFromList(this.eventList[time], value);

if (!this.eventList[time].length) {

Compute.removeFromList(this.timeList, time);

}

});

}

}

clearTriggerItem(time, value) {

Compute.removeFromList(this.waitingList[time], value);

}

3 waitingList、list的相关操作

// 撤销 waitingList 内的一切办法(回跳操作使用)

waitingCancel() {

for (let i in this.waitingList) {

let item = this.waitingList[i];

item.map((value, index, array) => {

// 撤销推迟办法

value.abort();

// 当然,推迟处理的办法还需求回来原先的list中

this.on({

time: i,

callBack: value

});

})

}

}

// 当即履行 waitingList 的一切办法(后跳操作使用)

waitingFinish() {

for (let i in this.waitingList) {

let item = this.waitingList[i];

item.map((vqqav群alue, index, array) => {

value.execut();

})

}

}

// 当即悉数履行一切list内的办法(播映完毕使用)

fini初中女生图片shList() {

this.timeList.map((value, index, array) => {

this.triggerByTime(value);

})

waitingFinish();

}

4. bug修正

4.1 打乱原有音讯履行次序的主要原因

4.2 相应措施

4.2.1 处理上述问题需求的两组数据

4.2.2 keyword

4.2.3 处理祈福,在线教育ESLive直播的时刻工作行列怎样完结?技术大牛在线教导!,凌潇肃计划详细过程剖析

1 将原有的延时/当即履行的办法封装为 promise。

const itemPromise = new Promise((resolve) => {

const triggerItem = new WaitingExecut({

waitTime: time - triggerTime,

callBack: () => {

item.callBack();

this.clearTriggerItem(time, item);

resolve();

},

});

if (!this.waitingList[time]) {

this.waitingList[time] = [triggerItem];

} else {

this.waitingList[time].push(triggerItem);

}

}).catch((e) => {

console.warn(e);

});

2 在触发序列挑选的办法履行前,先判别 promise 履行行列是否清空,假如未清空则不走下一步。

if (this.currentList.length) {

return;

}

...

3 在独立工作 promise 界说好后,当行将 promise 塞入 promise 行列中,然后将办法和当时时刻塞入办法索引行列,用以在悉数履行完后的铲除操作。

this.doingList.push(itemPromise);

4 在 promise 行列的 all 办法,即一切 promise 都为 resolve 时,使用 办法索引行列 在原数据上对已履行内容做铲除操作,之后清空 promise行列 和 办法索引队祈福,在线教育ESLive直播的时刻工作行列怎样完结?技术大牛在线教导!,凌潇肃列。

Promise.all(this.doingList).then(老公太小() => {

if (!this.options.needReplay) {

this.finishedTrigger(this.curr祈福,在线教育ESLive直播的时刻工作行列怎样完结?技术大牛在线教导!,凌潇肃entList);

}

this.doingL祈福,在线教育ESLive直播的时刻工作行列怎样完结?技术大牛在线教导!,凌潇肃ist = [];

this.currentList = [];

if (callBack) {

callBack();

}

}).catch((e) => {

console.error(e);

});

4.2.4 完好代码

triggerByLimit(time, limit = 0, customRule, callBack) {

// promise list not finished 对应 过程2

if (this.currentList.length) {

return;

}

// get the current conformance information queue

this.currentTime = time;

const currentTrigger = this.getTimeIndex(time + limit);

this.lastTime = time;

if (!currentTrigger.list.length) {

return;

云天售后服务管理软件

}

if (this.options.needReplay) {

this.lastIndex = Math.max(currentTrigger.index - 1, 0);

// console.error(this.lastIndex, currentTrigger);

}

let resultList = [].concat(this.resultList);

this.resultList = [];

currentTrigger.list.map((value) => {

resultList = resultList.concat(this.eventList[value]);

});

if (customRule) {

resultList = customRule(resultList);

}

if (resultList.length > 500) {

this.resultList = resultList.slice(500);

resultList = resultList.slice(0, 500);

}

resultList.map((value) => {

if (!value) {

return;

}

this.triggerByItem(value, time);

});

// 对应过程4

if (this.doingList.length) {

// const currentList = this.doingList.slice(0, 500);

Promise.all(this.doingList).then(() => {

if (!this.options.needReplay) {

this.finishedTrigger(this.currentList);

}

this.doingList = [];

this.currentList = [];

if (callBack) {

callBack();

}

}).catch((e) => {

console.error(e);

});

}

}

triggerByItem(item, triggerTime) {

if (!item) {

return;

}

const time = item.time;

this.currentList.push({

time,

item,

});

// 对应过程1 将原有的延时/当即履行的办法封装成 promise

const itemPromise = new Promise((resolve) => {

const triggerItem = new WaitingExecut({

waitTime: time - triggerTime,

callBack: () => {

item.callBack();

this.clearTriggerItem(time, item);

resolve();

},

});

if (!this.waitingList[time]) {

this.waitingList[time] = [triggerItem];

} else {

this.waitingList[time].push(triggerItem);

}

}).catch((e) => {

console.warn(e);

});

// 对应过程3 此处是将办法和当时时刻塞入办法索引行列

this.doingList.push(itemPromise);

}

完毕语

程序开发历来都不是一件单调的工作,当你愿意去考虑代码的细节和完结思路,你将会爱上你的易泽睿代码。

如文章中有不同的观念和主张,欢迎指正~

咱们正在寻求外包团队

EduSoho官方开发文档地址

EduSoho官网 https://www.edusoho.com/

EduSoho开源地址 https://github.com/edusoho/edusoho

---------------------

原创文章,作者:EduSoho小阔

版权归作者一切,请勿转载

想了解更多教育资讯

请重视【EduSoho网校体系】微信大众号​​​​

声明:该文观念仅代表作者自己,搜狐号系信息发布渠道,搜狐仅供给信息存储空间服务。
文章版权及转载声明:

作者:admin本文地址:http://www.bazhisuanming.cn/articles/1002.html发布于 2个月前 ( 05-03 01:35 )
文章转载或复制请以超链接形式并注明出处竞技宝官网_竞技宝官网app苹果版_竞技宝官网ios版