Civil & Structural Engineering
How to Handle Background Tasks in React Native Using Headless JS
Table of Contents
O que é o JS sem cabeça em Reagir nativo?
O JS sem cabeça é um recurso nativo integrado de React que permite executar o código JavaScript em segundo plano, mesmo quando a interface de usuário da aplicação não está ativa. Ao contrário da execução em primeiro plano, onde o aplicativo é visível e interativo, o JS sem cabeça executa tarefas como processos separados que não dependem do tópico principal de interface de usuário. Isto é essencial para operações que devem continuar após o usuário fechar o aplicativo ou antes de abri-lo – como sincronização de dados, processamento de notificações de push de entrada ou manuseio de alertas críticos no tempo. O JS sem cabeça faz ponte entre o tempo de execução JavaScript do Reagir nativo e as camadas nativas do Android e iOS, permitindo que você escreva lógica de fundo multiplataforma com o mínimo código nativo.
Casos comuns de uso para SJ sem cabeça
Entender quando usar o JS Headless ajuda você a decidir se ele se encaixa no seu projeto. Os cenários típicos incluem:
- Sincronização de dados – Carregar logs ou baixar conteúdo novo quando o aplicativo está em segundo plano.
- Manusear notificação – Realizar lógica personalizada quando uma notificação chega (por exemplo, atualizar um crachá, armazenar dados localmente) antes de mostrar o alerta.
- Actualizações de localização – Polação de coordenadas GPS em segundo plano para geofecção ou rastreamento em tempo real.
- Tarefas baseadas no tempo – Executar uma tarefa num intervalo programado (como limpeza diária) mesmo que o usuário não tenha aberto a aplicação.
- Ações rápidas da tela inicial – Realizando uma operação curta quando o usuário pressiona uma ação 3D Touch ou widget.
O JS sem cabeça não é projetado para cálculos de longo prazo ou pesados – o sistema pode matar seu processo de fundo se demorar muito tempo. Para o trabalho de fundo estendido, combine-o com serviços nativos como WorkManager (Android) ou BackgroundTasks[] (iOS).
Configuração do JS sem cabeça em Reagir Nativo: Passo a passo
A implementação do JS Headless envolve duas partes principais: criar um manipulador JavaScript e registá-lo no código nativo para cada plataforma.
1. Crie o gerenciador de fundo JavaScript
Comece por criar um novo ficheiro, por exemplo [[FLT: 0]]. Este ficheiro irá conter a função que executa quando a tarefa de fundo é activada. A função recebe um objecto [[FLT: 1]], que pode conter parâmetros passados do lado nativo.
// BackgroundTask.js
import { AppRegistry } from 'react-native';
const backgroundTask = async (taskData) => {
console.log('Background task started with data:', taskData);
// Your background logic goes here
// For example, fetch new data from an API
try {
const response = await fetch('https://api.example.com/sync');
const data = await response.json();
// Store data in AsyncStorage or a local database
console.log('Background sync complete');
} catch (error) {
console.error('Background task failed:', error);
// Optionally throw an error to let the system know
}
};
AppRegistry.registerHeadlessTask('BackgroundTask', () => backgroundTask);
Note que o manipulador deve ser uma função que retorna uma Promessa (ou uma função assincronizada). O sistema irá esperar que a Promessa resolva antes de considerar a tarefa completa. Se a Promessa rejeitar, o lado nativo poderá tratá- la como uma falha.
2. Registre a tarefa no código nativo Android
Android requer que você registre a tarefa sem cabeça em seu (ou ] dependendo da versão Nativa Reagir). Além disso, você precisa de um HeadlessJsTaskService para gerenciar o ciclo de vida da tarefa.
Passo A – Atualizar MainApplication.java
// android/app/src/main/java/com/yourapp/MainApplication.java
import com.facebook.react.HeadlessJsTaskService;
public class MainApplication extends Application implements ReactApplication {
// ... existing code
@Override
public void onCreate() {
super.onCreate();
// Initialize ReactNative instance as usual
// The task will be registered via AppRegistry in JavaScript
}
}
Não é necessário registro explícito em Java para a tarefa em si se você usar – Reagir Nativo automaticamente mapeia o manipulador JavaScript para uma tarefa nativa. No entanto, você deve criar um serviço que pode ser iniciado pelo sistema.
Passo B – Criar um Serviço de Tarefas Js sem Cabeça
Criar uma nova classe Java no mesmo pacote:
// android/app/src/main/java/com/yourapp/BackgroundTaskService.java
package com.yourapp;
import android.content.Intent;
import android.os.Bundle;
import com.facebook.react.HeadlessJsTaskService;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.jstasks.HeadlessJsTaskConfig;
public class BackgroundTaskService extends HeadlessJsTaskService {
@Override
protected HeadlessJsTaskConfig getTaskConfig(Intent intent) {
Bundle extras = intent.getExtras();
if (extras != null) {
return new HeadlessJsTaskConfig(
"BackgroundTask",
Arguments.fromBundle(extras),
5000, // timeout in ms
true // allows task to run in foreground as well
);
}
return null;
}
}
Este serviço extrai quaisquer extras da Intenção (como dados de uma notificação) e passa- os para o manipulador JavaScript. O tempo limite impede tarefas em fuga.
Passo C – Adicione o Serviço ao AndroidManifest.xml
<service android:name=".BackgroundTaskService" />
Agora qualquer módulo nativo pode iniciar este serviço usando um Intennt, ou você pode usar um receptor de transmissão para acionar a partir de uma notificação de push.
3. Configurar as capacidades de fundo do iOS
iOS é mais restritivo sobre execução de fundo. Para usar o JS Headless no iOS, você deve ativar modos de fundo apropriados e usar agendamento nativo (como notificações push ou busca de fundo).
Passo A – Activar os Modos de Fundo
Abra o seu projeto Xcode, vá para Assinando as Capacidades do &[[FLT: 1]], e adicione o [[FLT: 2] Modos de Antecedentes[[[FLT: 3]]. Verifique os modos de que sua aplicação precisa, por exemplo, “Requisição de Antecedentes” ou “Notificações remotas”.
Passo B – Métodos de Delegado de Aplicativos de Implementação
Em , implemente os métodos de delegada necessários para receber eventos de fundo e iniciar a tarefa sem cabeça.
// AppDelegate.m (Objective-C)
#import <React/RCTAppDelegate.h>
#import "AppDelegate.h"
#import <React/RCTBridge.h>
#import <React/RCTRootView.h>
@implementation AppDelegate
- (void)application:(UIApplication *)application
performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
// You can get the bridge from your ReactNative root view
RCTBridge *bridge = [self.rootView bridge];
[bridge.eventDispatcher sendAppEventWithName:@"BackgroundFetch"
body:@{@"taskName": @"BackgroundTask"}];
completionHandler(UIBackgroundFetchResultNewData);
}
@end
No lado JavaScript, você precisa ouvir o evento e iniciar a tarefa sem cabeça manualmente. No entanto, JS sem cabeça no iOS é mais comumente usado em conjunto com notificações de push – quando uma notificação chega, você pode executar o código sem cabeça antes de mostrar o alerta.
Para notificações push, implemente no AppDelegate e envie um evento para Reagir Nativo.
Acionando Tarefas de Fundo
Uma vez configurado, você pode ativar uma tarefa JS sem Cabeça de várias fontes:
- Introduza notificações[ (Android & iOS) – Use um receptor de transmissão personalizado no Android ou o delegado do aplicativo no iOS para iniciar o serviço quando uma notificação silenciosa chegar.
- Módulos nativos – Crie um módulo nativo que chama no Android ou publique uma notificação no iOS.
- Antecedentes buscar (iOS) – iOS chama seu delegado de aplicativos periodicamente; você pode usar essa oportunidade para disparar a tarefa sem cabeça.
- Alarmes – Use ou para programar a execução periódica.
Exemplo: Iniciando o serviço Android de um receptor de transmissão que escuta para uma ação personalizada:
public class AlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Intent serviceIntent = new Intent(context, BackgroundTaskService.class);
serviceIntent.putExtra("source", "alarm");
context.startService(serviceIntent);
}
}
Em seguida, registre o receptor no AndroidManifest.xml e agendar um alarme usando .
Melhores práticas para uma operação de fundo confiável
As tarefas de fundo são inerentemente frágeis – o SO pode matar o seu processo a qualquer momento. Siga estas diretrizes para tornar as suas tarefas JS sem cabeça robustas:
- Mantenha as tarefas curtas. Mire em menos de 30 segundos de execução. Use os timeouts (os 5000ms em nosso exemplo) para evitar tarefas suspensas.
- Erros de mão graciosamente. Enrole sua lógica em tentativa/captura. Se a tarefa falhar, considere fazer login localmente usando um repórter de falhas (como Sentry) e não bloqueie a UI.
- Use padrões offline. Uma vez que as tarefas de fundo muitas vezes são executadas sem garantias de rede, implemente tentativas e guarde operações falhadas para mais tarde.
- Evite o gerenciamento de estado pesado. Não confie em Redux ou React state – tarefas de fundo executadas em um contexto JavaScript separado. Use o AsyncStorage, SQLite (react-native-sqlite-storage), ou armazenamento seguro para persistência de dados.
- Teste em dispositivos reais. O simulador Android emulador e iOS se comportam de forma diferente do hardware físico. Teste com tela de dispositivo desligada e em modo Doze (Android) ou Low Power Mode (iOS).
- Respeitar a otimização da bateria. Use com um bloqueio de despertar no Android para evitar que a CPU durma, mas solte o bloqueio prontamente. No iOS, intervalos de busca de fundo são gerenciados pelo sistema – respeite o tempo concedido.
Depurando Tarefas JS sem Cabeça
Depurar o código de fundo é complicado porque você não pode usar o inspetor de DevTools do Chrome quando a interface não estiver ativa. Use estas técnicas:
- Logcat (Android) – Adicionar declarações; eles aparecem em logcat com a tag “ReactNativeJS”.
- Registros de arquivos locais – Escreva entradas de log em um arquivo no dispositivo e recuperá-los mais tarde.
- Flipper – Reagir Nativo Flipper pode capturar logs de console de tarefas sem cabeça (garantir que você definir ] para true em seu plugin Flipper).
- Native loging – Use em seu serviço Java para rastrear quando a tarefa começa e termina.
Limitações e Considerações
Sem cabeça JS não é uma bala de prata. Entenda suas limitações para evitar surpresas:
- Nenhuma interação com UI. Você não pode renderizar visualizações ou mostrar alertas dentro de uma tarefa sem cabeça. Use notificações push para informar o usuário dos resultados.
- Tarefa única por processo. O serviço sem cabeça do Nativo Reagir executa apenas uma tarefa JavaScript de cada vez. Se você precisar de várias operações de background paralelas, considere usar serviços nativos (WorkManager no Android, BGTaskScheduler no iOS).
- iOS restritions. iOS acelera fortemente a execução de fundo. JS sem cabeça no iOS é confiável apenas para tarefas curtas desencadeadas por notificações de push ou busca de background – o sistema pode atrasar ou impedir a execução se o usuário sair do aplicativo.
- No Redux store. Como mencionado anteriormente, o contexto JavaScript sem cabeça não compartilha o mesmo store Redux como o aplicativo de primeiro plano. Use o armazenamento persistente para passar dados entre os dois contextos.
- Terminação do aplicativo. Se o usuário forçar-fecha seu aplicativo no Android 12+ ou iOS, as tarefas de fundo podem não ser executadas até que o usuário abra o aplicativo novamente.
Comparação com outras bibliotecas de fundo
O JS sem cabeça do Nativo é o mecanismo integrado de nível mais baixo. Para muitos casos de uso, os pacotes comunitários fornecem uma API mais conveniente:
| Library | Platform | Features |
|---|---|---|
| react-native-background-fetch | Android & iOS | Periodic background fetching with system‑managed scheduling; supports Headless JS internally. |
| react-native-background-actions | Android & iOS | Runs a long‑running foreground service (with persistent notification) – can execute heavy tasks. |
| WorkManager (Android only via native bridge) | Android | Deferrable, reliable background work with constraints (network, battery); does not use Headless JS by default. |
| Headless JS (vanilla) | Android & iOS | Simple, built‑in, no extra dependencies; best for short tasks triggered by push or alarms. |
Se sua tarefa deve ser executada mesmo após uma reinicialização, ou você precisa de agendamento complexo, considere envolver uma implementação nativa do WorkManager e expondo-a através de um módulo nativo React. O JS sem cabeça permanece excelente para trabalhos leves de “fogo-e-esquecimento”.
Exemplo completo: Sincronizar dados sobre a notificação de envio
Vamos colocar tudo junto com um cenário realista: quando uma notificação silenciosa push chega no Android, o aplicativo baixar os dados mais recentes de uma API e armazená-lo localmente. O usuário nunca vê uma mudança de UI – os dados estão prontos quando eles abrem o aplicativo.
Android – Receptor de empurrar
Criar um receptor de transmissão que ouça a ação push (por exemplo, a partir de FCM):
public class PushReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Intent serviceIntent = new Intent(context, BackgroundTaskService.class);
serviceIntent.putExtra("action", "syncData");
context.startService(serviceIntent);
}
}
Registre-o no AndroidManifest.xml com um filtro de intenção para sua ação push (ou use FirebaseMessagingService ] para iniciar o serviço diretamente).
Manipulador JavaScript
// BackgroundTask.js (expanded)
import { AppRegistry } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
const backgroundTask = async (taskData) => {
const { action } = taskData;
if (action === 'syncData') {
try {
const response = await fetch('https://api.example.com/latest-data');
const json = await response.json();
await AsyncStorage.setItem('cachedData', JSON.stringify(json));
console.log('Data synced successfully');
} catch (error) {
// Write error to a local log
const errorLog = await AsyncStorage.getItem('errorLog');
const newLog = (errorLog ? errorLog + '\n' : '') + new Date().toISOString() + ': ' + error.message;
await AsyncStorage.setItem('errorLog', newLog);
}
}
};
AppRegistry.registerHeadlessTask('BackgroundTask', () => backgroundTask);
Quando o usuário reabrir o aplicativo, o primeiro plano pode ler e atualizar a interface imediatamente, criando uma experiência off-line perfeita.
Desempenho e Impacto da Bateria
As tarefas sem cabeça são executadas no mesmo motor JavaScript que a aplicação principal, mas num contexto separado. Cada tarefa gira uma nova instância JS sem cabeça, que consome memória e CPU. Para minimizar a perda de bateria:
- Use o menor tempo de descanso que ainda permite que o trabalho para completar.
- Não faça sondagens frequentes – prefira gatilhos baseados em push.
- No Android, ligue para do serviço após o término da tarefa (HeadlessJsTaskService faz isso automaticamente quando a Promessa resolve).
- Combine com APIs conscientes da bateria como WorkManager para Android e BGTaskScheduler para iOS se precisar de trabalho periódico.
Conclusão
O JS sem cabeça é uma ferramenta poderosa no cinto do desenvolvedor nativo React para lidar com tarefas de fundo curtas que devem ser executadas independentemente da visibilidade do aplicativo. Ao configurar um manipulador JavaScript e conectá-lo com gatilhos de fundo nativos – tais como notificações de push, alarmes ou busca de fundo – você pode construir aplicativos responsivos e direcionados a dados que se sintam sempre ligados. Lembre-se de seguir as melhores práticas em torno de brevidade, manipulação de erros e limitações específicas de plataforma para garantir que suas operações de fundo sejam confiáveis e amigáveis a bateria. Para agendamento avançado ou tarefas mais longas, complemente o Headless JS com bibliotecas dedicadas como ou WorkManager nativo.
Para mais informações, consulte a documentação oficial React Native em . JS sem cabeça (Android) e JS sem cabeça (iOS). Verifique também a biblioteca de reactância-nativa-fundo-fetch para gerenciamento periódico de tarefas.