Preload.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. const log$d = new Logger("preload");
  2. class Preload {
  3. constructor(e) {
  4. E(this, "config");
  5. E(this, "allKeys", []);
  6. E(this, "oldResourcesDeleted", !1);
  7. E(this, "requests", {
  8. simple: {
  9. stopped: !0,
  10. requests: {}
  11. },
  12. observer: {
  13. stopped: !0,
  14. requests: {}
  15. },
  16. full: {
  17. stopped: !0,
  18. requests: {}
  19. }
  20. });
  21. this.modelManager = e,
  22. this.init(e.appId)
  23. }
  24. init(e) {
  25. reporter.updateBody({
  26. appId: e
  27. })
  28. }
  29. static getTimeoutBySize(e) {
  30. return e ? e < 500 * 1e3 ? 30 * 1e3 : e < 1e3 * 1e3 ? 60 * 1e3 : 100 * 1e3 : 100 * 1e3
  31. }
  32. async getConfig(e) {
  33. if (this.config)
  34. return this.config;
  35. const {preload: t} = await this.modelManager.requestConfig();
  36. return t ? (this.config = t,
  37. Promise.resolve(t)) : Promise.reject("no preload config")
  38. }
  39. async getAllKeys() {
  40. if (this.allKeys.length)
  41. return this.allKeys;
  42. try {
  43. const e = await modelTable.getAllKeys();
  44. return this.allKeys = e,
  45. e
  46. } catch {
  47. const t = "preload getAllKeys error";
  48. return log$d.error(t),
  49. Promise.reject(t)
  50. }
  51. }
  52. stop(e) {
  53. e === "serverless" && (e = "observer"),
  54. this.requests[e].stopped = !0;
  55. const t = this.requests[e].requests;
  56. Object.keys(t).forEach(r=>{
  57. http$1.canceler.removePending(r),
  58. delete t[r]
  59. }
  60. )
  61. }
  62. clearPreload(e) {
  63. this.requests[e].stopped = !1,
  64. this.allKeys = []
  65. }
  66. async start(e, t, r) {
  67. let n = Date.now()
  68. , o = 0;
  69. try {
  70. if (e === "serverless" && (e = "observer"),
  71. !this.requests[e])
  72. return Promise.reject(new ParamError("invalid stage name: " + e));
  73. this.clearPreload(e);
  74. const a = await this.getConfig(e)
  75. , s = await this.getAllKeys();
  76. try {
  77. await this.deleteOldResources(a.assetUrls.map(d=>d.url), s)
  78. } catch (d) {
  79. log$d.error(d)
  80. }
  81. const {baseUrls: l, assetUrls: u, observeUrls: c} = a;
  82. let h;
  83. switch (e) {
  84. case "simple":
  85. h = l;
  86. break;
  87. case "observer":
  88. h = u;
  89. break;
  90. case "full":
  91. h = u;
  92. break;
  93. default:
  94. h = u
  95. }
  96. let f = h.filter(d=>!s.includes(d.url));
  97. r && isFunction(r) && (f = f.filter(r)),
  98. o = f.length,
  99. log$d.debug("keysNeedToPreload", f),
  100. f.length || t && t(h.length, h.length),
  101. n = Date.now(),
  102. await this._preload(e, f, t),
  103. log$d.infoAndReportMeasurement({
  104. tag: e,
  105. startTime: n,
  106. metric: "assetsPreload",
  107. extra: {
  108. total: o
  109. }
  110. });
  111. return
  112. } catch (a) {
  113. let s = a;
  114. return (this.requests[e].stopped || axios.isCancel(a)) && (s = new PreloadCanceledError),
  115. log$d.infoAndReportMeasurement({
  116. tag: e,
  117. startTime: n,
  118. metric: "assetsPreload",
  119. extra: {
  120. total: o
  121. },
  122. error: s,
  123. reportOptions: {
  124. immediate: !0
  125. }
  126. }),
  127. Promise.reject(s)
  128. }
  129. }
  130. deleteOldResources(e, t) {
  131. if (!this.oldResourcesDeleted)
  132. this.oldResourcesDeleted = !0;
  133. else
  134. return Promise.resolve();
  135. const r = t.filter(n=>!e.includes(n));
  136. return log$d.debug("keysNeedToDelete", r),
  137. log$d.warn("keysNeedToDelete", r.length),
  138. Promise.all(r.map(n=>modelTable.delete(n)))
  139. }
  140. async _preload(e, t, r) {
  141. const n = t.length;
  142. if (!n)
  143. return Promise.resolve();
  144. let o = 0;
  145. const a = window.setInterval(()=>{
  146. r && r(o, n),
  147. o >= n && window.clearInterval(a)
  148. }
  149. , 1e3);
  150. return mapLimit(t, 10, async s=>{
  151. const {size: l, url: u} = s;
  152. return this.requests[e].stopped ? Promise.reject(new PreloadCanceledError) : http$1.get({
  153. url: u,
  154. timeout: Preload.getTimeoutBySize(l),
  155. responseType: "blob",
  156. retry: 2,
  157. beforeRequest: ()=>{
  158. this.requests[e].requests[u] = !0
  159. }
  160. }).then(async c=>{
  161. const h = c.data;
  162. if (!(h instanceof Blob))
  163. return log$d.error("request blob failed, type:", typeof h, u),
  164. Promise.reject("request blob failed " + u);
  165. const f = await blobToDataURI$1(h);
  166. try {
  167. await modelTable.put({
  168. url: u,
  169. model: f
  170. });
  171. return
  172. } catch (d) {
  173. return log$d.error("unable to add data to indexedDB", d),
  174. Promise.reject(new InternalError("preload db error"))
  175. }
  176. }
  177. ).then(()=>{
  178. o++,
  179. delete this.requests[e].requests[u]
  180. }
  181. , c=>(delete this.requests[e].requests[u],
  182. window.clearInterval(a),
  183. Promise.reject(c)))
  184. }
  185. )
  186. }
  187. }