浏览代码

improve eventSource lifecycle handling

Olivier Massot 3 年之前
父节点
当前提交
d73dec2f72
共有 1 个文件被更改,包括 30 次插入20 次删除
  1. 30 20
      pages/cmf_licence/organization.vue

+ 30 - 20
pages/cmf_licence/organization.vue

@@ -34,7 +34,7 @@
 </template>
 
 <script lang="ts">
-import {defineComponent, onMounted, onUnmounted, Ref, ref, useContext} from "@nuxtjs/composition-api";
+import {defineComponent, onBeforeMount, onBeforeUnmount, onMounted, onServerPrefetch, onUnmounted, Ref, ref, useContext} from "@nuxtjs/composition-api";
 import {HTTP_METHOD, QUERY_TYPE} from "~/types/enums";
 import DataPersister from "~/services/data/dataPersister";
 import {DataPersisterArgs} from "~/types/interfaces";
@@ -48,45 +48,57 @@ export default defineComponent({
     let pending: Ref<boolean> = ref(false)
     let fileUrl: Ref<string | null> = ref(null)
     let eventSource: Ref<EventSource | null> = ref(null)
-    let async: boolean = true
+
+    const sseOpened = () => {
+      return eventSource.value !== null && eventSource.value?.readyState === EventSource.OPEN
+    }
 
     const submit = async () => {
       const response = await DataPersister.request(
         '/api/export/cmf-licence/organization',
         HTTP_METHOD.POST,
-        { type: QUERY_TYPE.DEFAULT, data: { format: 'pdf', async: async }, withCredentials: true } as DataPersisterArgs
+        { type: QUERY_TYPE.DEFAULT, data: { format: 'pdf', async: sseOpened() }, withCredentials: true } as DataPersisterArgs
       )
-      if (async) {
+      if (sseOpened()) {
         pending.value = true
       } else {
-        console.warn('File is downloaded synchronously')
+        console.warn('File downloaded synchronously')
         fileUrl.value = JSON.parse(response).url
       }
     }
 
     const unsubscribe = async () => {
-      if (eventSource.value !== null) {
-        eventSource.value.onerror = null
-        eventSource.value.close()
-        eventSource.value = null
+      if (eventSource.value === null || eventSource.value.readyState === EventSource.CLOSED) {
+        return
       }
+      console.log('SSE - Close subscription')
+      eventSource.value.close()
     }
 
     const subscribe = async () => {
-      await unsubscribe()
+      if (sseOpened()) {
+        console.error('SSE - Already subscribed to the event source')
+        return
+      }
+      if (process.server) {
+        console.error('SSE - Cannot subscribe on server side')
+        return
+      }
 
       const url = new URL($config.baseUrl_mercure)
       url.searchParams.append('topic', "access/" + store.state.profile.access.id)
 
-      eventSource.value = new EventSourcePolyfill(url.toString(), { withCredentials: true });
+      eventSource.value = new EventSourcePolyfill(
+        url.toString(),
+        { withCredentials: true, heartbeatTimeout: 3600 * 1000 }
+      );
 
-      eventSource.value.onerror = event => {
-        async = false
-        console.error('Error while subscribing to the EventSource, fallback to sync mode : ' + JSON.stringify(event))
-        unsubscribe()
+      eventSource.value.onerror = (event) => {
+        console.error('SSE - An error happened : ' + JSON.stringify(event))
+        eventSource.value?.close()
       }
-      eventSource.value.onopen = event => {
-        console.log('Listening for events...')
+      eventSource.value.onopen = () => {
+        console.log('SSE - Listening for events...')
       }
       eventSource.value.onmessage = event => {
         const data = JSON.parse(event.data)
@@ -99,14 +111,12 @@ export default defineComponent({
       subscribe()
     })
 
-    onUnmounted(() => {
+    onBeforeUnmount(() => {
       unsubscribe()
     })
 
     return {
-      eventSource,
       submit,
-      subscribe,
       pending,
       fileUrl
     }