先说一下问题场景,还是关于之前的调整时间之后再进行弹窗。
先说一下理想的效果:
首先要说明的就是不是每个任务都有后继任务,就算有后继任务如果后继任务不符合条件(开始和截止时间啊都存在)也不会进行弹窗。
起初想靠弹窗组件来解决判定问题——弹窗打开后进行判定,如果不符合条件再将弹窗关闭,虽然可以正常执行,并且基本上人眼看不出来进行过弹窗,但是多次试验后发现仍会出现闪屏的情况,所以放弃了这个写法。
先不论弹窗顺序,首先试一下能不能正常调用弹窗。
一开始想的是在父组件中循环调用之前写的batchSettingTime
方法来解决。
先介绍一下这个方法:
需要的参数:更改前的时间,更改后的时间,当前任务,当前任务的后置任务。
这个方法首先获取了当前任务的后置任务的任务详情主要也就是获取了这些任务的开始、截止时间,再去判断这些任务中是否有需要展示的任务(开始/截止时间完备),如果有再去调用弹窗。
batchSettingTime(. . .) {
// 后置任务中是否存在配置完全的任务
havePostTasksAllDate = false;
// 订阅所有后置任务的任务详情
let ListOgPostTasks = [] as Observable<Task>[];
postTasks.forEach(
task => {
ListOfPostTasks.push(
this.taskStore
.dispatch(fetchTaskDetail, task.id))}
)
// 利用combineLatest获取判断获取完所有的任务详情后再去做处理
combineLatest(ListOfPostTasks)
.subscribe(
data => {
data.foreach(
task => {
if(task.duedate && task.startDate) {
havePostTasksAllDate = true;
}
}
)
// 如果满足条件再去调用弹窗
if(havePostTasksAllDate) {
const changeDate = newDate - oldDate;
const dialogRef = this.util.thyDialog.open(xxxComponent, {将task, changedate,oldDate传入弹窗})
}
// 因为如果在关闭后进行调用的话由于弹窗组件已经销毁,导致其中的变量获取不到,所以要在其关闭前进行处理
dialogRef.beforeClosed().subScribe
if(dialofRef.componentInstance.selectedTasks.lenth != 0 && dialogRef.componentInstance.beSubmit) {
dialogRef.componentInstance.selectedTasks.forEach(
task => {
this.taskDependentStore.fetchDependentTasks(task.id)
this.taskDependentStore.select(TaskDepenDentStore.postDependentTasks)
.pipe(takeUntile(dialogRef.afterClosed())), skip(1))
.subscribe(data => {
// 由于要及时的取消订阅旧的观察者,所以当此弹窗关闭后取消订阅
// 由于select会返回两次内容,所以通过skip(1)来跳过获取旧的内容
postTasks = data;
this.taskStore.dispatch(fetchTaskDetail, task.id)
.subscribe(
task => {
this.batchSettingTime(task.dueDate - changeDate, task.dueDate, task, postTasks)
})
})
})
}
});
}
起初由于没有及时取消对taskDependentStore.select(TaskDepenDentStore.postDependentTasks)
的订阅导致每次执行fetchDependentTasks
都会触发订阅导致每当关闭,打开新弹窗都会触发之前的订阅,从而导致弹窗的多次额外弹出。
此外由于之前所说select
方法正常情况下就会触发两次,可以由自订变量来获取第二次的内容而不获取第一次的旧的内容。
但是这么写总归还是不规范,并且也不方便测试,如果有像combineLatest
的这种rxjs操作符,那么应该也会有类似于只获取第二次observable内容或者跳过第一次observable内容的操作符,查询rxjs官网后发现果然有。
xxxObservable
.pipe(skip(1))
.subscribe({
console.log('跳过了第一次发送的内容')
})
测试之后发现上面的代码如果在只有只有一个任务的情况下是可以正常执行的,比如:任务一=》任务二=》任务三=》任务四
当我们改变任务一,就会弹出任务二的弹窗,改变任务二就会有任务三的弹窗以此类推。
但是当我们改变多个并列任务时就会出现问题——一次性弹出四个弹窗,并且弹窗中内容也相互影响——任务二的后继出现在了任务三弹窗中,任务三的后继出现在了任务二弹窗中。
猜测也还是由于循环中的fetchDependentTasks
执行多次导致的,并且在弹窗组件中也会获取任务的后置任务及后置任务的任务详情,并且这些也都是靠store获取的,同时有多个组件同时调用缓存就产生了混乱,所以猜测只要解决多个弹窗的问题,应该就能解决弹窗内任务混乱的问题。
比如拿两个并列任务来举例,其执行过程猜测如下。
但是这张图肯定是有问题的,因为我们用了skip(1)来避免获取旧数据,后来又去掉skip(1)再去执行发现弹窗生成了六次,这个问题仍在解决中。
那么为什么只有一个任务就没问题呢?
因为其执行过程如下:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。