3. lib / js / consumeJson.js

1import { ProblemDetails } from "./ProblemDetails.js"
2
3/**
4 * Espera a que la promesa de un fetch termine. Si
5 * hay error, lanza una excepción. Si no hay error,
6 * interpreta la respuesta del servidor como JSON y
7 * la convierte en una literal de objeto.
8 *
9 * @param { string | Promise<Response> } servicio
10 */
11export async function consumeJson(servicio) {
12
13 if (typeof servicio === "string") {
14 servicio = fetch(servicio, {
15 headers: { "Accept": "application/json, application/problem+json" }
16 })
17 } else if (!(servicio instanceof Promise)) {
18 throw new Error("Servicio de tipo incorrecto.")
19 }
20
21 const respuesta = await servicio
22
23 const headers = respuesta.headers
24
25 if (respuesta.ok) {
26 // Aparentemente el servidor tuvo éxito.
27
28 if (respuesta.status === 204) {
29 // No contiene texto de respuesta.
30
31 return { headers, body: {} }
32
33 } else {
34
35 const texto = await respuesta.text()
36
37 try {
38
39 return { headers, body: JSON.parse(texto) }
40
41 } catch (error) {
42
43 // El contenido no es JSON. Probablemente sea texto de un error.
44 throw new ProblemDetails(respuesta.status, headers, texto,
45 "/error/errorinterno.html")
46
47 }
48
49 }
50
51 } else {
52 // Hay un error.
53
54 const texto = await respuesta.text()
55
56 if (texto === "") {
57
58 // No hay texto. Se usa el texto predeterminado.
59 throw new ProblemDetails(respuesta.status, headers, respuesta.statusText)
60
61 } else {
62 // Debiera se un ProblemDetails en JSON.
63
64 try {
65
66 const { title, type, detail } = JSON.parse(texto)
67
68 throw new ProblemDetails(respuesta.status, headers,
69 typeof title === "string" ? title : respuesta.statusText,
70 typeof type === "string" ? type : undefined,
71 typeof detail === "string" ? detail : undefined)
72
73 } catch (error) {
74
75 if (error instanceof ProblemDetails) {
76 // El error si era un ProblemDetails
77
78 throw error
79
80 } else {
81
82 throw new ProblemDetails(respuesta.status, headers, respuesta.statusText,
83 undefined, texto)
84
85 }
86
87 }
88
89 }
90
91 }
92
93}
94
95// Permite que los eventos de html usen la función.
96window["consumeJson"] = consumeJson
skip_previous skip_next