1. Prompt y alcance
Una notificación de estado de pedido ofrece las acciones Ver pedido, Confirmar entrega y Contactar a soporte. La aplicación puede estar cerrada, una ventana puede ya existir o la sesión puede haber expirado. Diseña el flujo con acciones de Notification y explica cómo la navegación del navegador coopera con notificationclick.
2. Lo que el entrevistador está evaluando
- Entender que el
navigatedel cuerpo y elnavigatede la acción son URLs separadas, donde la URL de una acción tiene precedencia sobre el manejo personalizado. - Saber que una acción sin URL llega a
notificationclick, y mantener vivo el trabajo asíncrono conevent.waitUntil. - Validar URLs del mismo origen, permisos, estado de autenticación y el ciclo de vida del Service Worker.
- Usar etiquetas, claves de idempotencia de negocio y recuperación de clientes para evitar confirmaciones o ventanas duplicadas.
3. Preguntas para clarificar primero
- ¿Puede Confirmar entrega ser una navegación GET, o debe ser una API POST con confirmación?
- ¿Debería una sesión expirada abrir el inicio de sesión primero y reanudar la acción después?
- ¿Puede la acción de soporte dirigirse a un dominio externo de servicio al cliente?
- ¿Debería enfocarse una ventana existente, enviársele un mensaje o debería abrirse una nueva ventana?
4. Respuesta en treinta segundos
Mapearía las acciones de solo lectura de ver y ayuda a URLs del mismo origen en lista permitida, mientras dejo la acción de confirmación que genera efectos secundarios sin navigate. El Service Worker maneja esa acción a través de una API idempotente y luego enruta a la página de resultados. Se verifica cada URL, el trabajo asíncrono se envuelve en waitUntil y se enfoca una ventana controlada existente antes de abrir un fallback.
5. Análisis detallado paso a paso
Paso 1: Declarar URLs de cuerpo y de acción
await self.registration.showNotification("Order #123", {
body: "Choose an action",
tag: "order-123",
navigate: "/orders/123",
data: { orderId: "123", version: 4 },
actions: [
{ action: "view", title: "View order", navigate: "/orders/123" },
{ action: "confirm", title: "Confirm delivery" },
{ action: "help", title: "Contact support", navigate: "/support/orders/123" },
],
});Las URLs del cuerpo y de las acciones deben ser rutas validadas del mismo origen. Usa tag para actualizar o agrupar notificaciones de un pedido, y limita data a identificadores no sensibles necesarios para la recuperación.
Paso 2: Separar acciones de solo lectura y con efectos secundarios
Las acciones de ver y ayuda solo navegan y pueden ser manejadas por el navegador. Confirmar no tiene navigate, por lo que llega a notificationclick; debe llamar a una API de servidor idempotente en lugar de codificar un cambio de estado en los parámetros de consulta.
Paso 3: Implementar fallback de notificationclick
self.addEventListener("notificationclick", (event) => {
event.notification.close();
const { orderId, version } = event.notification.data ?? {};
if (event.action !== "confirm" || !orderId) return;
event.waitUntil(confirmDelivery(orderId, version).then(() =>
focusOrOpen(`/orders/${encodeURIComponent(orderId)}?confirmed=1`)));
});El código de producción debe capturar fallas de red, versiones obsoletas y respuestas no autorizadas, y permitir que la página de resultados presente la recuperación. waitUntil mantiene vivo el evento del Service Worker hasta que la promesa se resuelva.
Paso 4: Manejar ventanas y recuperación de inicio de sesión
focusOrOpen debe coincidir con una ventana controlada del mismo origen, enviar una ruta validada a través de postMessage y llamar a clients.openWindow solo cuando no exista una ventana adecuada. Si el inicio de sesión expiró, transporta solo un estado objetivo de corta duración; después de iniciar sesión, la página debe obtener y autorizar el pedido nuevamente.
Paso 5: Seguridad, permisos e idempotencia
El permiso de notificación controla la visualización, no la autorización del pedido. Restringe el protocolo, origen y ruta; usa el ID del pedido, la versión o una clave de idempotencia para evitar confirmaciones duplicadas. El descarte, las etiquetas duplicadas y los clics simultáneos en dispositivos requieren un comportamiento explícito de máquina de estados en el servidor.
6. Respuesta modelo de alta calidad
Usaríanavigatedel mismo origen para ver y ayuda, y manejaría Confirmar entrega ennotificationclickporque tiene un efecto secundario. El Service Worker usawaitUntilpara llamar a una API idempotente con la versión y clave del pedido, luego enfoca una ventana existente o abre la ruta de resultados. Cada URL está en una lista permitida, el permiso no es autorización y la recuperación del inicio de sesión vuelve a verificar el acceso. Las pruebas cubren clics en el cuerpo y en acciones, repeticiones, modo fuera de línea, versiones obsoletas y múltiples ventanas.
7. Errores comunes
- Desencadenar la confirmación a través de una URL GET → la precarga o repeticiones causan efectos secundarios → llama a un POST idempotente desde el evento.
- Asumir que una acción sin URL abre la URL del cuerpo → el comportamiento es ambiguo → manéjalo explícitamente en
notificationclick. - Poner el pedido completo en
data→ se filtra información sensible → transporta un identificador y vuelve a obtener los datos autorizados. - Omitir
waitUntilalrededor del trabajo asíncrono → el Worker puede terminar prematuramente → gestiona cada promesa crítica. - Crear siempre una nueva ventana → estado dividido → busca y enfoca primero una ventana del mismo origen.
8. Preguntas de seguimiento
Pregunta de seguimiento 1: ¿Cuál tiene prioridad, action.navigate o notificationclick?
Cuando una acción tiene su propio navigate, el navegador puede usar esa URL. Una acción sin ella necesita un manejo personalizado de notificationclick.
Pregunta de seguimiento 2: ¿Por qué no poner la confirmación en la URL?
La navegación puede ser precargada, reproducida o recibir clics repetidos y no puede representar de forma segura un efecto secundario. La confirmación pertenece a una transición de estado de servidor autorizada e idempotente.
Pregunta de seguimiento 3: ¿Cómo te recuperas de un inicio de sesión expirado?
Almacena un estado objetivo de corta duración protegido contra alteraciones al abrir el inicio de sesión. Después de iniciar sesión, la página obtiene el pedido, verifica la autorización y luego restaura la ruta de resultados.
Pregunta de seguimiento 4: ¿Cómo demuestras que no hay ejecuciones duplicadas?
Desencadena clics en el cuerpo y en las acciones repetidamente a través de ventanas y dispositivos con la misma versión de pedido y clave de idempotencia, luego verifica que el servidor realice solo una transición de confirmación.