Saltar al contenido

Por qué async por defecto

Un comando síncrono corre en el hilo del bucle de eventos y bloquea la ventana; uno asíncrono, no. Las tres formas de declararlo, cuál elegir en cada caso, y el atributo que hace asíncrono a un comando síncrono.

Las tres formas

La tercera fila es la que resuelve el caso incómodo: hay código que no es asíncrono y que tarda. SQLite no tiene entrada y salida asíncrona real —lo dice el nivel 42—, una librería de compresión es síncrona, un cálculo intensivo no se vuelve asíncrono por escribirlo distinto. Marcarlo con ese atributo lo saca del hilo principal sin tener que reescribir nada.

El síntoma

Un comando síncrono que tarda produce un fallo muy reconocible y que no parece un fallo del comando:

TXT
el usuario pulsa un botón  → la ventana deja de responder  → el cursor de espera del sistema  → macOS puede llegar a decir «la aplicación no responde»  → todo vuelve a la normalidad cuando el comando acaba

Lo característico es que la interfaz se congela entera, no solo la parte que esperaba el dato. Y como el frontend sigue teniendo su promesa pendiente, desde JavaScript parece que todo va bien: no hay error, no hay traza, solo una aplicación quieta.

Si alguna vez ves ese comportamiento, la primera hipótesis es un comando síncrono con trabajo dentro. La segunda es el hilo principal ocupado por otra cosa, que es el nivel 24.

Cuándo es aceptable un comando síncrono

La lista es corta y conviene que lo sea:

  • Devolver un valor del estado que ya está en memoria y no exige tomar un cerrojo que alguien pueda estar sosteniendo.
  • Devolver una constante o algo derivado de la configuración.
  • Un cálculo trivial sobre datos pequeños que ya tienes.

Y aun así, la ventaja de que sea síncrono es prácticamente nula: invoke devuelve una promesa igual —nivel 13.1—, así que el frontend no se entera. No ganas nada, y te expones a que alguien meta trabajo dentro dentro de seis meses.

De ahí la regla del nivel: asíncrono por defecto, y síncrono solo cuando puedas justificarlo en una línea.

Lo que esto implica para el frontend

Como todos los comandos devuelven una promesa, el frontend no distingue las tres formas y eso es bueno: puedes cambiar un comando de síncrono a asíncrono sin tocar una línea de la interfaz.

La consecuencia práctica: si descubres que un comando tarda más de lo que pensabas, la corrección es del lado de Rust y no afecta al contrato. Es una de las pocas cosas en este framework que se puede arreglar sin coordinar los dos lados.