transistorsoft / react-native-background-fetch

Periodic callbacks in the background for both IOS and Android
MIT License
1.43k stars 191 forks source link

BackgroundFetch.finish does not stop scheduled tasks #476

Closed rakshitbharat closed 5 months ago

rakshitbharat commented 5 months ago

Your Environment

Expected Behavior

finish should stop and terminate the ongoing task

Actual Behavior

finish is not working so you cant stop the running task

import BackgroundFetch from 'react-native-background-fetch';

/**
 * Class BackgroundTaskManager is designed to manage background tasks using
 * react-native-background-fetch. However, the finish method does not seem
 * to terminate the ongoing tasks as expected.
 */
class BackgroundTaskManager {
  /**
   * Configures the task manager with provided arguments for background execution.
   */
  static configure(...args) {
    return BackgroundFetch.configure(...args);
  }

  /**
   * Schedules a new background task using react-native-background-fetch.
   */
  static scheduleTask(...args) {
    console.log('Scheduling task with args:', args);
    return BackgroundFetch.scheduleTask(...args);
  }

  /**
   * Attempts to stop the background task using react-native-background-fetch's
   * finish method. However, this does not seem to stop the ongoing task.
   */
  static finish(...args) {
    console.log('Finishing task with args:', args);
    return BackgroundFetch.finish(...args);
  }
}

export default BackgroundTaskManager;
christocracy commented 5 months ago

.finish(taskId) does not "stop" a periodic task from continuing -- it's merely a signal to the OS "I'm finished with this task invocation".

See the API docs .stop(taskId).

rakshitbharat commented 5 months ago

any way to force stop the running task ?

christocracy commented 5 months ago

To signal to the OS that the currently running task is finished, call .finish(taskId).

rakshitbharat commented 5 months ago

this class want meant to do the same but not working, the task is not terminated

christocracy commented 5 months ago

Do you understand the difference between .stop(taskId) and .finish(taskId)?

rakshitbharat commented 5 months ago

if i have to terminate the on going task should i first programatically call finish and then stop ?

christocracy commented 5 months ago

Yes

rakshitbharat commented 5 months ago
import BackgroundFetch from 'react-native-background-fetch';
import { DeviceEventEmitter } from 'react-native';

/**
 * BackgroundTaskManager manages background tasks using react-native-background-fetch.
 * Issue: The finish method does not terminate the ongoing tasks as expected.
 */
class BackgroundTaskManager {
  static configStartFunction = null;

  /**
   * Configures the task manager for background execution.
   * @param {...any} args - Arguments for configuration.
   * @returns The result of the BackgroundFetch configuration.
   */
  static configure(...args) {
    // Store the start function provided in arguments for later use
    this.configStartFunction = args[1];

    // A wrapper for the task execution
    const taskWrapper = async (taskId) => {
      console.log(`Executing task with taskId: ${taskId}`);

      // Listen for a stop signal
      DeviceEventEmitter.addListener('stopBackgroundTask', () => {
        console.log(`Received stop signal for task ${taskId}`);
        BackgroundFetch.finish(taskId);
      });

      // Execute the provided start function if it exists
      if (this.configStartFunction) {
        this.configStartFunction(taskId);
      }
    };

    // Replace the original start function with the wrapper in arguments
    args[1] = taskWrapper;
    return BackgroundFetch.configure(...args);
  }

  /**
   * Schedules a new background task.
   * @param {...any} args - Arguments for scheduling the task.
   * @returns The result of scheduling the task.
   */
  static scheduleTask(...args) {
    console.log('Scheduling task with args:', args);
    return BackgroundFetch.scheduleTask(...args);
  }

  /**
   * Attempts to stop the background task.
   * Issue: This method does not stop the ongoing task.
   * @param {string} taskId - The ID of the task to stop.
   */
  static finish(taskId) {
    console.log('Finishing task with taskId:', taskId);
    DeviceEventEmitter.emit('stopBackgroundTask', taskId);
    BackgroundFetch.finish(taskId);
  }
}

export default BackgroundTaskManager;

no luck tried all way

rakshitbharat commented 5 months ago

I found very strange phenomena, if we will use infinite loop like ""while"" in case you use any library or even promise it will never ever going to stop the task. and there is no way i can find to terminate the callback function in case the callback function contains the while loop

christocracy commented 5 months ago

I don't know what you're trying to do. You're making this way more complex than it actually is.

You get a finite number of seconds to complete each invocation of your callback function before the OS gets impatient for consuming too much time in the background. Call .finish(taskId) to signal to the OS that your task invocation is complete.

When you no longer wish for the plug-in to schedule more invocations of your callback function, call .stop(taskId) and your callback will no longer be scheduled to execute in the future.

rakshitbharat commented 5 months ago

I want to run a task in which i can terminate it any time when neede, i tried almost all library but no luck, i want any way to run the task and terminate it, also note i want to run it in foreground only.

christocracy commented 5 months ago

Calling .finish(taskId) does not STOP your code from running.

It is merely a signal to the OS "I'm finished. You may put the app to sleep if you wish".

You CANNOT do an infinite loop in your callback and expect that calling .finish(taskId) is going to magically make your infinite while-loop stop executing.

rakshitbharat commented 5 months ago

any option to do so ? i have a hardware based communication where if user wants we dismiss all the operations immediately

christocracy commented 5 months ago

"You CANNOT do" really means "CANNOT do".

It doesn't mean "maybe there's an option to do it".

It's up to you to make your own flag to exit out of an infinite loop.

rakshitbharat commented 5 months ago

Thanks for reply i found a way to send a emit to change the value of the flag of while loop to false from finish function this way the loop is getting exit on time.