1 | |
2 | |
3 | |
4 | invocaServicio("srv/lista.php") |
5 | .then(respuesta => { |
6 | |
7 | const lista = respuesta.body |
8 | |
9 | if (Array.isArray(lista)) { |
10 | |
11 | let render = "" |
12 | for (const modelo of lista) { |
13 | |
14 | |
15 | |
16 | const nombre = |
17 | typeof modelo.nombre === "string" ? htmlentities(modelo.nombre) : "" |
18 | const color = |
19 | typeof modelo.color === "string" ? htmlentities(modelo.color) : "" |
20 | render += |
21 | `<dt>${nombre}</dt> |
22 | <dd>${color}</dd>` |
23 | } |
24 | |
25 | |
26 | if (self instanceof WorkerGlobalScope) { |
27 | |
28 | self.postMessage({ resultado: render }) |
29 | } |
30 | } |
31 | }) |
32 | .catch(muestraErrorEnWorker) |
33 | |
34 | const ProblemDetails_InternalServerError = 500 |
35 | |
36 | class ProblemDetails extends Error { |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | constructor(status, title, detail, type) { |
45 | super(title) |
46 | |
47 | this.status = status |
48 | |
49 | this.type = type |
50 | |
51 | this.title = title |
52 | |
53 | this.detail = detail |
54 | } |
55 | |
56 | } |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | function muestraErrorEnWorker(error) { |
64 | if (error === null) { |
65 | console.log("Error") |
66 | self.postMessage({ error: "Error" }) |
67 | } else if (error instanceof ProblemDetails) { |
68 | let mensaje = error.title |
69 | if (error.detail) { |
70 | mensaje += `\n\n${error.detail}` |
71 | } |
72 | mensaje += `\n\nCódigo: ${error.status}` |
73 | if (error.type) { |
74 | mensaje += ` ${error.type}` |
75 | } |
76 | console.error(mensaje) |
77 | console.error(error) |
78 | self.postMessage({ error: mensaje }) |
79 | } else { |
80 | console.error(error) |
81 | self.postMessage({ error: error.message }) |
82 | } |
83 | } |
84 | |
85 | const JsonResponse_OK = 200 |
86 | const JsonResponse_Created = 201 |
87 | const JsonResponse_NoContent = 204 |
88 | |
89 | class JsonResponse { |
90 | |
91 | |
92 | |
93 | |
94 | |
95 | |
96 | constructor(status, body, location) { |
97 | |
98 | this.status = status |
99 | |
100 | this.body = body |
101 | |
102 | this.location = location |
103 | } |
104 | |
105 | } |
106 | |
107 | |
108 | |
109 | |
110 | |
111 | |
112 | |
113 | |
114 | export async function invocaServicio(servicio) { |
115 | let f = servicio |
116 | if (typeof servicio === "string") { |
117 | f = fetch(servicio, { |
118 | headers: { "Accept": "application/json, application/problem+json" } |
119 | }) |
120 | } else if (!(f instanceof Promise)) { |
121 | throw new Error("Servicio de tipo incorrecto.") |
122 | } |
123 | const respuesta = await f |
124 | if (respuesta.ok) { |
125 | if (respuesta.status === JsonResponse_NoContent) { |
126 | return new JsonResponse(JsonResponse_NoContent) |
127 | } |
128 | const texto = await respuesta.text() |
129 | try { |
130 | const body = JSON.parse(texto) |
131 | if (respuesta.status === JsonResponse_Created) { |
132 | const location = respuesta.headers.get("location") |
133 | return new JsonResponse(JsonResponse_Created, body, |
134 | location === null ? undefined : location) |
135 | } else { |
136 | return new JsonResponse(JsonResponse_OK, body) |
137 | } |
138 | } catch (error) { |
139 | |
140 | throw new ProblemDetails(ProblemDetails_InternalServerError, |
141 | "Problema interno en el servidor.", texto) |
142 | } |
143 | } else { |
144 | const texto = await respuesta.text() |
145 | try { |
146 | const { type, title, detail } = JSON.parse(texto) |
147 | throw new ProblemDetails(respuesta.status, |
148 | typeof title === "string" ? title : "", |
149 | typeof detail === "string" ? detail : undefined, |
150 | typeof type === "string" ? type : undefined) |
151 | } catch (error) { |
152 | if (error instanceof ProblemDetails) { |
153 | throw error |
154 | } else { |
155 | |
156 | throw new ProblemDetails(respuesta.status, respuesta.statusText, texto) |
157 | } |
158 | } |
159 | } |
160 | } |
161 | |
162 | |
163 | |
164 | |
165 | |
166 | |
167 | |
168 | |
169 | function htmlentities(texto) { |
170 | return texto.replace(/[<>"']/g, textoDetectado => { |
171 | switch (textoDetectado) { |
172 | case "<": return "<" |
173 | case ">": return ">" |
174 | case '"': return """ |
175 | case "'": return "'" |
176 | default: return textoDetectado |
177 | } |
178 | }) |
179 | } |