Skip to content

Commit

Permalink
fix: refresh sse stream when src update (#15)
Browse files Browse the repository at this point in the history
* fix: refresh stream when src update

* fix: work with same slotId

* refactor: refine event handler

* test: unit test

* refactor: refine code

* refactor: fix type

* fix: fix function binding
  • Loading branch information
bill-min committed Apr 28, 2023
1 parent fc36c57 commit cc259f4
Show file tree
Hide file tree
Showing 47 changed files with 529 additions and 307 deletions.
82 changes: 35 additions & 47 deletions src/components/micro-frame-slot/component/node.marko
Original file line number Diff line number Diff line change
@@ -1,51 +1,39 @@
import StreamSource from "../../stream-source/component/StreamSource";
$ const sourceName = input.from;
$ let err;
import { getOrCreateStreamSource } from "../../stream-source/component/helper";

$ {
if (!out.global.STREAM_SOURCE_MAP_SERVER || !out.global.STREAM_SOURCE_MAP_SERVER.has(sourceName))
err = new Error(`micro-frame-sse ${sourceName} is not defined.`);
const streamSource = getOrCreateStreamSource(input.from, out);
const stream = streamSource.slot(input.slot);
let finishLoading;
const loadingPromise =
input.loading && new Promise((res) => (finishLoading = res));
}

<if(err)>
$ if (!input.catch) throw err;
<${input.catch}(err)/>
</if>
<else>
$ const streamSource = out.global.STREAM_SOURCE_MAP_SERVER.get(sourceName);
$ const stream = streamSource.slot(input.slot);
$ let finishLoading;
$ {
const loadingPromise =
input.loading && new Promise((res) => (finishLoading = res));
}
<div id=component.id data-slot=input.slot data-from=input.from>
<macro name="wait">
<await(stream.next())
client-reorder=input.clientReorder
timeout=input.timeout
>
<@then|{ value, done }|>
<if(!done)>
$!{value}
<wait/>
</if>
<else>
$ finishLoading && finishLoading();
</else>
</@then>
<@catch|e|>
<div id=component.id data-slot=input.slot data-from=input.from>
<macro name="wait">
<await(stream.next())
client-reorder=input.clientReorder
timeout=input.timeout
>
<@then|{ value, done }|>
<if(!done)>
$!{value}
<wait/>
</if>
<else>
$ finishLoading && finishLoading();
<${input.catch}(e)/>
</@catch>
</await>
</macro>
$ out.bf("@_", component, true);
<if(stream)>
<if(input.loading)>
<await(loadingPromise) placeholder=input.loading client-reorder/>
</if>
<wait/>
</else>
</@then>
<@catch|e|>
$ finishLoading && finishLoading();
<${input.catch}(e)/>
</@catch>
</await>
</macro>
$ out.bf("@_", component, true);
<if(stream)>
<if(input.loading)>
<await(loadingPromise) placeholder=input.loading client-reorder/>
</if>
$ out.ef();
</div>
</else>
<wait/>
</if>
$ out.ef();
</div>
34 changes: 22 additions & 12 deletions src/components/micro-frame-slot/component/web.component.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { StreamWritable } from "../../stream-source/component/StreamWritable";
import { STREAM_SOURCE_MAP_CLIENT } from "../../stream-source/component/StreamSource";
import StreamSource from "../../stream-source/component/StreamSource";
import getWritableDOM from "writable-dom";
import { getOrCreateStreamSource } from "../../stream-source/component/helper";

interface Input {
slot: string;
Expand Down Expand Up @@ -36,34 +37,38 @@ export = {
};
},
onMount() {
// Only trigger a new load if this wasn't ssr'd, or the src has changed.
this.streamSource = getOrCreateStreamSource(this.input.from);
this.handleSrcChange = this.handleSrcChange.bind(this);
this.streamSource.onInvalidate(this.handleSrcChange);
this.onUpdate();
},
handleSrcChange(src: string) {
this.curSrc = src;
this.forceUpdate();
},
onDestroy() {
this.slot?.end();
this.streamSource.offInvalidate(this.handleSrcChange);
},
async onUpdate() {
if (this.slotId === this.input.slot && this.from === this.input.from)
if (
this.slotId === this.input.slot &&
this.from === this.input.from &&
this.prevSrc === this.curSrc
)
return;

this.state.loading = true;
this.state.err = undefined;
this.slotId = this.input.slot;
this.from = this.input.from;
this.prevSrc = this.curSrc;

let writable: ReturnType<typeof getWritableDOM> | undefined;
let err: Error | undefined;

try {
const streamSource = STREAM_SOURCE_MAP_CLIENT.get(this.from);
// In case of micro-frame-sse pure server-side rendered,
// throw error when the slot trying to connect to the stream
if (!streamSource)
throw new Error(
`micro-frame-sse ${this.from} is not defined or server-side rendered.`
);

this.slot = streamSource.slot(this.slotId);
this.slot = this.streamSource.slot(this.slotId);

if (!this.slot) {
return;
Expand Down Expand Up @@ -98,9 +103,14 @@ export = {
el: HTMLDivElement;
slotId: string | undefined;
from: string | undefined;
prevSrc: string | undefined;
curSrc: string | undefined;
slot: StreamWritable | undefined;
streamSource: StreamSource;
onUpdate(): unknown;
onCreate(): unknown;
onMount(): unknown;
onDestroy(): unknown;
forceUpdate(): unknown;
handleSrcChange(src: string): unknown;
};
2 changes: 1 addition & 1 deletion src/components/micro-frame-slot/component/web.marko
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ static function noop() {}
We put the streamed html in a preserved fragment.
This allows Marko to avoid diffing that section.
-->
$ out.bf("@_", component, !state.err && component.slotId === input.slot && component.from === input.from).ef();
$ out.bf("@_", component, !state.err && component.slotId === input.slot && component.from === input.from && component.prevSrc === component.curSrc).ef();
</div>

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<div>
Host app
</div>
<button>
Change
</button>
<script>
$csr_then_change_src_index_C=(window.$csr_then_change_src_index_C||[]).concat({"l":1,"w":[["s0-8",0,{},{"f":1}]],"t":["hjKmUtFR"]})
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<div>
Host app
</div>
<button>
Change
</button>
<div />
<div />
<div />
<script>
$csr_then_change_src_index_C=(window.$csr_then_change_src_index_C||[]).concat({"l":1,"w":[["s0-8",0,{},{"f":1}]],"t":["hjKmUtFR"]})
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<div>
Host app
</div>
<button>
Change
</button>
<div />
<div>
<p>
test_html for slot_1
</p>
</div>
<div />
<script>
$csr_then_change_src_index_C=(window.$csr_then_change_src_index_C||[]).concat({"l":1,"w":[["s0-8",0,{},{"f":1}]],"t":["hjKmUtFR"]})
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<div>
Host app
</div>
<button>
Change
</button>
<div />
<div>
<p>
test_html for slot_1
</p>
</div>
<div>
<p>
test_html for slot_2
</p>
</div>
<script>
$csr_then_change_src_index_C=(window.$csr_then_change_src_index_C||[]).concat({"l":1,"w":[["s0-8",0,{},{"f":1}]],"t":["hjKmUtFR"]})
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<div>
Host app
</div>
<button>
Change
</button>
<div />
<div>
<p>
test_html for slot_1
</p>
next chunk for slot_1
</div>
<div>
<p>
test_html for slot_2
</p>
</div>
<script>
$csr_then_change_src_index_C=(window.$csr_then_change_src_index_C||[]).concat({"l":1,"w":[["s0-8",0,{},{"f":1}]],"t":["hjKmUtFR"]})
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<div>
Host app
</div>
<button>
Change
</button>
<div />
<div />
<div />
<script>
$csr_then_change_src_index_C=(window.$csr_then_change_src_index_C||[]).concat({"l":1,"w":[["s0-8",0,{},{"f":1}]],"t":["hjKmUtFR"]})
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<div>
Host app
</div>
<button>
Change
</button>
<div />
<div>
<p>
test_html for slot_1
</p>
</div>
<div />
<script>
$csr_then_change_src_index_C=(window.$csr_then_change_src_index_C||[]).concat({"l":1,"w":[["s0-8",0,{},{"f":1}]],"t":["hjKmUtFR"]})
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<div>
Host app
</div>
<button>
Change
</button>
<div />
<div>
<p>
test_html for slot_1
</p>
</div>
<div>
<p>
test_html for slot_2
</p>
</div>
<script>
$csr_then_change_src_index_C=(window.$csr_then_change_src_index_C||[]).concat({"l":1,"w":[["s0-8",0,{},{"f":1}]],"t":["hjKmUtFR"]})
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<div>
Host app
</div>
<button>
Change
</button>
<div />
<div>
<p>
test_html for slot_1
</p>
after src change
</div>
<div>
<p>
test_html for slot_2
</p>
</div>
<script>
$csr_then_change_src_index_C=(window.$csr_then_change_src_index_C||[]).concat({"l":1,"w":[["s0-8",0,{},{"f":1}]],"t":["hjKmUtFR"]})
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,17 @@
</p>
</div>
<div
data-src="embed"
id="GENERATED-4"
style="display:none"
>
<noscript
id="GENERATED-5"
/>
</div>
<div
data-from="test2"
data-slot="slot_1"
id="GENERATED-6"
>
<p>
test_2_html for slot_1
</p>
</div>
style="display:none"
/>
<script>
function $af(d,a,e,l,g,h,k,b,f,c){c=$af;if(a&&!c[a])(c[a+="$"]||(c[a]=[])).push(d);else{e=document;l=e.getElementById("af"+d);g=e.getElementById("afph"+d);h=e.createDocumentFragment();k=l.childNodes;b=0;for(f=k.length;b&lt;f;b++)h.appendChild(k.item(0));g&&g.parentNode.replaceChild(h,g);c[d]=1;if(a=c[d+"$"])for(b=0,f=a.length;b&lt;f;b++)c(a[b])}};$af(0);$af(1)
</script>
Loading

0 comments on commit cc259f4

Please sign in to comment.