Skip to content

Commit fe2860a

Browse files
committed
fix: scan
1 parent a1c9090 commit fe2860a

1 file changed

Lines changed: 66 additions & 19 deletions

File tree

web/app/composables/useOpenCv.ts

Lines changed: 66 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,44 +29,91 @@ export function loadOpenCv(): Promise<Cv> {
2929
return
3030
}
3131
const w = window as unknown as { cv?: any }
32+
let done = false
3233

33-
const settle = (): void => {
34+
const finish = (): boolean => {
3435
const cv = w.cv
35-
if (!cv) {
36-
reject(new Error('OpenCV global missing after load'))
37-
return
36+
if (done || !cv || typeof cv.Mat !== 'function') {
37+
return false
3838
}
39-
if (typeof cv.then === 'function') {
40-
// Newer emscripten builds export a module factory promise.
41-
cv.then((m: Cv) => {
42-
w.cv = m
43-
resolve(m)
44-
}).catch(reject)
39+
done = true
40+
resolve(cv)
41+
return true
42+
}
43+
44+
// The docs.opencv.org build exposes a global `cv` that is an Emscripten
45+
// Module: its `then` is NOT a real Promise (no `.catch`), and `cv.Mat`
46+
// only appears once the wasm runtime is initialised. We hook every signal
47+
// and, crucially, poll as a safety net so the promise ALWAYS settles
48+
// (otherwise the page hangs forever on "chargement du moteur").
49+
let wired = false
50+
const wire = (): void => {
51+
const cv = w.cv
52+
if (!cv || wired) {
4553
return
4654
}
47-
if (cv.Mat) {
48-
resolve(cv)
49-
return
55+
wired = true
56+
try {
57+
if (typeof cv.then === 'function') {
58+
cv.then((m: Cv) => {
59+
if (m && typeof m.Mat === 'function') {
60+
w.cv = m
61+
}
62+
finish()
63+
})
64+
}
65+
} catch {
66+
/* Emscripten thenable can throw if called twice — ignored. */
67+
}
68+
cv.onRuntimeInitialized = (): void => {
69+
finish()
5070
}
51-
cv.onRuntimeInitialized = (): void => resolve(w.cv)
5271
}
5372

73+
let tries = 0
74+
const poll = window.setInterval(() => {
75+
tries += 1
76+
wire()
77+
if (finish()) {
78+
window.clearInterval(poll)
79+
} else if (tries >= 300) {
80+
// ~30 s
81+
window.clearInterval(poll)
82+
if (!done) {
83+
done = true
84+
reject(new Error('OpenCV: délai d’initialisation dépassé'))
85+
}
86+
}
87+
}, 100)
88+
5489
if (w.cv) {
55-
settle()
90+
wire()
5691
return
5792
}
5893
const existing = document.getElementById('opencv-js') as HTMLScriptElement | null
5994
if (existing) {
60-
existing.addEventListener('load', settle)
61-
existing.addEventListener('error', () => reject(new Error('OpenCV failed to load')))
95+
existing.addEventListener('load', wire)
96+
existing.addEventListener('error', () => {
97+
window.clearInterval(poll)
98+
if (!done) {
99+
done = true
100+
reject(new Error('OpenCV failed to load'))
101+
}
102+
})
62103
return
63104
}
64105
const s = document.createElement('script')
65106
s.id = 'opencv-js'
66107
s.async = true
67108
s.src = OPENCV_URL
68-
s.onload = settle
69-
s.onerror = (): void => reject(new Error('OpenCV failed to load'))
109+
s.onload = wire
110+
s.onerror = (): void => {
111+
window.clearInterval(poll)
112+
if (!done) {
113+
done = true
114+
reject(new Error('OpenCV failed to load'))
115+
}
116+
}
70117
document.head.appendChild(s)
71118
})
72119
return cvPromise

0 commit comments

Comments
 (0)