Qu'est-ce que le JS sans tête dans Réaction autochtone?

Contrairement à l'exécution avant plan, où l'application est visible et interactive, Headless JS exécute des tâches comme des processus séparés qui ne dépendent pas du fil principal de l'interface utilisateur. Ceci est essentiel pour les opérations qui doivent se poursuivre après la fermeture de l'application ou avant qu'elles ne l'ouvrent – comme la synchronisation des données, le traitement des notifications de poussée entrantes ou la gestion des alertes critiques dans le temps. Headless JS règle l'écart entre React Native , l'exécution JavaScript et les couches natives d'Android et d'iOS, ce qui vous permet d'écrire une logique de fond multiplateforme avec un code natif minimal.

Cas d'utilisation courante pour les JS sans tête

Comprendre quand utiliser Headless JS vous aide à décider si elle convient à votre projet. Les scénarios typiques incluent:

  • Synchronisation des données[ – Téléchargement de journaux ou téléchargement de nouveaux contenus lorsque l'application est en arrière-plan.
  • Manipulation de la notification de type Push – Effectuer une logique personnalisée lorsqu'une notification arrive (par exemple, mettre à jour un badge, stocker des données localement) avant de montrer l'alerte.
  • – Mises à jour de l'emplacement – Coordonnées GPS de sondage en arrière-plan pour le géofençage ou le suivi en temps réel.
  • Tâches basées sur le temps – Exécuter un travail à un intervalle programmé (comme le nettoyage quotidien) même si l'utilisateur n'a pas ouvert l'application.
  • Actions rapides depuis l'écran d'accueil – Effectuer une opération courte lorsque l'utilisateur appuie sur une action 3D Touch ou un widget.

Pour les travaux de fond prolongés, combinez-les avec des services natifs comme WorkManager (Android) ou [BackgroundTasks[ (iOS).

Mettre en place des systèmes de communication sans tête dans les Autochtones réagissent : étape par étape

Mise en œuvre Headless JS comporte deux parties principales : créer un gestionnaire JavaScript et l'enregistrer dans le code natif pour chaque plateforme. Nous passerons par les deux parties.

1. Créer le gestionnaire de fond JavaScript

Commencez par créer un nouveau fichier, par exemple . Ce fichier contiendra la fonction qui s'exécute lorsque la tâche d'arrière-plan est déclenchée. La fonction reçoit un objet , qui peut contenir les paramètres passés du côté natif.

// 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);

Notez que le gestionnaire doit être une fonction qui renvoie une promesse (ou une fonction async). Le système attendra que la promesse de résoudre avant de considérer la tâche terminée. Si la promesse rejette, le côté natif peut la traiter comme un échec.

2. Enregistrer la tâche dans Android Native Code

Android vous demande d'enregistrer la tâche sans tête dans votre (ou selon la version Native de React). De plus, vous avez besoin d'un [HeadlessJsTaskService pour gérer le cycle de vie de la tâche.

Étape A – Mettre à jour 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
 }
}

Aucune inscription explicite en Java n'est nécessaire pour la tâche elle-même si vous utilisez – React Native masque automatiquement le gestionnaire JavaScript à une tâche native. Cependant, vous devez créer un service qui peut être démarré par le système.

Étape B – Créer un service de travail sans tête

Créer une nouvelle classe Java dans le même paquetage:

// 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;
 }
}

Ce service extrait tous les extras de l'Intent (comme les données d'une notification) et les transmet au gestionnaire JavaScript. Le délai empêche les tâches fugueuses.

Étape C – Ajouter le service à AndroidManifest.xml

<service android:name=".BackgroundTaskService" />

Maintenant, tout module natif peut démarrer ce service en utilisant une intention, ou vous pouvez utiliser un récepteur de radiodiffusion pour le déclencher à partir d'une notification de poussée.

3. Configuration des capacités de fond iOS

iOS est plus restrictif en ce qui concerne l'exécution de background. Pour utiliser Headless JS sur iOS, vous devez activer les modes de background appropriés et utiliser la programmation native (comme les notifications push ou background fall).

Étape A – Activer les modes de fond

Ouvrez votre projet Xcode, allez dans Signing & Capacities, et ajoutez la fonction Modes de fond. Vérifiez les modes dont votre application a besoin, par exemple -Refold ou -Remote notifications.

Étape B – Mettre en œuvre les méthodes de délégation de l'application

Dans , mettre en œuvre les méthodes de délégation requises pour recevoir les événements de fond et commencer la tâche sans tête.

// 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

Du côté JavaScript, vous devez écouter l'événement et commencer la tâche sans tête manuellement. Cependant, Headless JS sur iOS est plus couramment utilisé avec les notifications de poussée – quand une notification arrive, vous pouvez exécuter le code sans tête avant de montrer l'alerte.

Pour les notifications de poussée, implémentez dans AppDelegate et envoyez un événement à React Native.

Déclenchement des tâches de fond

Une fois configuré, vous pouvez déclencher une tâche JS sans tête à partir de différentes sources:

  • Notifications de pression (Android & iOS) – Utilisez un récepteur de diffusion personnalisé sur Android ou le délégué de l'application sur iOS pour démarrer le service lorsqu'une notification silencieuse arrive.
  • Modèles natifs – Créez un module natif qui appelle sur Android ou affiche une notification sur iOS.
  • Refet de fond (iOS) – iOS appelle votre délégué d'application périodiquement; vous pouvez utiliser cette occasion pour lancer la tâche sans tête.
  • Alarmes – Utiliser ou pour planifier l'exécution périodique.

Exemple: Démarrer le service Android à partir d'un récepteur de radiodiffusion qui écoute pour une action personnalisée:

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);
 }
}

Puis enregistrez le récepteur dans AndroidManifest.xml et planifiez une alarme en utilisant .

Meilleures pratiques pour une opération de référence fiable

Les tâches de fond sont intrinsèquement fragiles – le système d'exploitation peut tuer votre processus à tout moment. Suivez ces lignes directrices pour rendre vos tâches JS Headless robustes:

  • Garder les tâches courtes. Visez moins de 30 secondes d'exécution. Utilisez des temps d'exécution (les 5000ms dans notre exemple) pour empêcher les tâches suspendues.
  • Erreurs de poignée gracieusement. Enveloppez votre logique dans essai/catcher. Si la tâche échoue, envisagez de vous enregistrer localement en utilisant un rapporteur d'écrasement (comme Sentry) et ne bloquez pas l'interface utilisateur.
  • Utilisez des modèles hors ligne] Comme les tâches de fond sont souvent exécutées sans garantie réseau, implémentez des rétries et stockez des opérations qui ont échoué plus tard.
  • Éviter la gestion de l'état lourd.] Ne pas compter sur l'état Redux ou React – les tâches de fond s'exécutent dans un contexte JavaScript séparé. Utilisez AsyncStorage, SQLite (réact-native-sqlite-storage), ou sécurisez le stockage pour la persistance des données.
  • Test sur les appareils réels. L'émulateur Android et le simulateur iOS se comportent différemment du matériel physique. Testez avec l'écran de l'appareil désactivé et en mode Doze (Android) ou Mode basse puissance (iOS).
  • Respecter l'optimisation de la batterie. Utilisez avec un verrouillage de veille sur Android pour empêcher le processeur de dormir, mais relâchez le verrouillage rapidement. Sur iOS, les intervalles de récupération de fond sont gérés par le système – respectez le temps accordé.

Déboguer les tâches JS sans tête

Déboguage de fond code est difficile parce que vous ne pouvez pas utiliser l'inspecteur Chrome DevTools lorsque l'interface utilisateur n'est pas active. Utilisez ces techniques:

  • Logcat (Android) – Ajouter des instructions ; elles apparaissent dans logcat avec la balise --ReactNativeJS.
  • Logs de fichiers locaux[ – Écrivez des entrées de journaux dans un fichier sur l'appareil et récupérez-les plus tard.
  • Flipper – React Native Flipper peut capturer les journaux de console des tâches sans tête (assurer que vous définissez à true dans votre plugin Flipper).
  • Native log[ – Utilisez dans votre service Java pour tracer quand la tâche commence et se termine.

Limites et considérations

JS sans tête n'est pas une balle d'argent. Comprendre ses limites pour éviter les surprises:

  • Aucune interaction d'interface utilisateur Vous ne pouvez pas afficher de vues ou d'alertes dans une tâche sans tête. Utilisez des notifications push pour informer l'utilisateur des résultats.
  • Une seule tâche par processus. Le service sans tête React Native=1 n'exécute qu'une seule tâche JavaScript à la fois. Si vous avez besoin de plusieurs opérations parallèles de fond, envisagez d'utiliser des services natifs (WorkManager sur Android, BGTaskScheduler sur iOS).
  • iOS restrictions. iOS exécute l'arrière-plan avec des gaz lourds. Les JS sans tête sur iOS ne sont fiables que pour les tâches courtes déclenchées par des notifications poussées ou des recherches d'arrière-plan – le système peut retarder ou empêcher l'exécution si l'utilisateur force-quitte l'application.
  • Aucune boutique Redux] Comme mentionné précédemment, le contexte JavaScript sans tête ne partage pas le même magasin Redux que l'application de premier plan. Utilisez un stockage persistant pour transmettre des données entre les deux contextes.
  • Fin de l'application. Si l'utilisateur ferme votre application sur Android 12+ ou iOS, les tâches de fond ne peuvent pas s'exécuter tant que l'utilisateur n'ouvre pas l'application à nouveau.

Comparaison avec d'autres bibliothèques de référence

React Native , JS Headless est le mécanisme intégré le plus bas. Pour de nombreux cas d'utilisation, les paquets communautaires offrent une API plus pratique :

LibraryPlatformFeatures
react-native-background-fetchAndroid & iOSPeriodic background fetching with system‑managed scheduling; supports Headless JS internally.
react-native-background-actionsAndroid & iOSRuns a long‑running foreground service (with persistent notification) – can execute heavy tasks.
WorkManager (Android only via native bridge)AndroidDeferrable, reliable background work with constraints (network, battery); does not use Headless JS by default.
Headless JS (vanilla)Android & iOSSimple, built‑in, no extra dependencies; best for short tasks triggered by push or alarms.

Si votre tâche doit être exécutée même après un redémarrage, ou si vous avez besoin d'un calendrier complexe, envisagez d'emballer une implémentation native WorkManager et de l'exposer via un module natif React Native.

Exemple complet : Synchronisation des données sur la notification de poussée

Let , tout est mis en place avec un scénario réaliste: quand une notification de poussée silencieuse arrive sur Android, l'application télécharge les dernières données d'une API et les stocke localement. L'utilisateur ne voit jamais un changement d'interface utilisateur – les données sont prêtes quand elles ouvriront l'application.

Android – Récepteur de poussée

Créer un récepteur de radiodiffusion qui écoute l'action de poussée (p. ex., à 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);
 }
}

Enregistrez-le dans AndroidManifest.xml avec un filtre intentionnel pour votre action de poussée (ou utilisez FirebaseMessageService -] pour démarrer le service directement).

Mainlevée 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);

Lorsque l'utilisateur rouvre l'application, le premier plan peut lire et mettre à jour immédiatement l'interface utilisateur, créant ainsi une expérience sans faille hors ligne-première expérience.

Performance et impact de la batterie

Les tâches sans tête fonctionnent dans le même moteur JavaScript que l'application principale, mais dans un contexte séparé. Chaque tâche fait tourner une nouvelle instance JS sans tête, qui consomme la mémoire et le processeur.

  • Utilisez le délai le plus court qui permet encore de terminer le travail.
  • Ne pas effectuer de sondages fréquents – préférez les déclencheurs basés sur la poussée.
  • Sur Android, appelez du service après la fin de la tâche (HeadlessJsTaskService fait cela automatiquement lorsque la Promesse résout).
  • Combinez avec des API de batterie comme WorkManager pour Android et BGTaskScheduler pour iOS si vous avez besoin de travail périodique.

Conclusion

En installant un gestionnaire JavaScript et en le connectant avec des déclencheurs de fond natifs – tels que des notifications de poussée, des alarmes ou des récupérations de fond – vous pouvez construire des applications réactives, basées sur des données qui se sentent toujours sur. N'oubliez pas de suivre les meilleures pratiques concernant la brièveté, la manipulation des erreurs et les limitations spécifiques à la plate-forme pour vous assurer que vos opérations de fond sont à la fois fiables et compatibles avec la batterie. Pour des tâches avancées ou plus longues, ajoutez Headless JS à des bibliothèques dédiées comme ou WorkManager natif.

Pour plus de détails, voir la documentation officielle de React Native sur Headless JS (Android)[ et Headless JS (iOS). Vérifiez également la bibliothèque react-native-background-fetch pour la gestion périodique des tâches.