isolates_helper 0.4.0-dev.1 copy "isolates_helper: ^0.4.0-dev.1" to clipboard
isolates_helper: ^0.4.0-dev.1 copied to clipboard

unlisted

An easy way to create multiple long live isolates for computation, support try-catch block.

Isolates Helper #

  • An easy way to create multiple long live isolates for computation.

  • This package is based on the power of isolate_manager (which is also written by me) but can be used with mutiple functions.

  • Support try-catch block.

Usage #

Define the number of isolates you want to live with concurrent parameter.

void main() async {
  // Create 3 isolates to solve the problems
  final isolates = IsolatesHelper(concurrent: 3);

  // Listen for the results from the stream.
  isolates.stream.listen((result) {
    if (result is double) {
      print('Stream get addFuture: $result');
    } else {
      print('Stream get add: $result');
    }
  });

  // Compute the values. The return type and parameter type will respect the type
  // of the function.
  final added = await isolates.compute(addFuture, [1.1, 2.2]);
  print('add: 1.1 + 2.2 = $added');

  // Multiple computations at the same time are allowed. It will be queued
  // automatically.
  for (int i = 0; i < 10; i++) {
    isolates(add, [i, i]).then((value) async {
      print('add: $i + $i = $value');
    });
  }

  // Stop the IsolateHelper instance after 5 seconds
  Timer(Duration(seconds: 5), () {
    isolates.stop();
  });
}

@pragma('vm:entry-point')
Future<double> addFuture(List<double> values) async {
  return values[0] + values[1];
}

@pragma('vm:entry-point')
int add(List<int> values) {
  return values[0] + values[1];
}

Use @pragma('vm:entry-point') notation to avoid the function being trimmed when building in release mode.

Here is the ways to use try-catch block:

// Catch the error from the stream
isolates.stream.listen((result) {
  print('Stream get add: $result');
}).onError((e) {
  print('Error from stream: $e');
});

// Catch the error from the try-catch block
try {
  await isolates.compute(addException, [1, 1]);
} catch (e) {
  print('Error from try-catch: $e');
}

The first compute will automatically wait for all isolates to started before doing the computation, if you want to wait for it manually, you can use:

await isolates.ensureStarted;

Or you can check if the current isolates are started or still in processing by using:

bool isStarted = isolates.isStarted;

You can restart all the isolates with:

await isolates.restart();

Remember to stop the isolates when you don't need it:

await isolates.stop();

Worker #

  • Step 1 Download isolates_helper/worker/worker.dart or copy the below code to the file named worker.dart:

    worker.dart
    // ignore_for_file: avoid_web_libraries_in_flutter, depend_on_referenced_packages
    
    import 'dart:async';
    import 'dart:html' as html;
    import 'dart:js' as js;
    
    import 'package:isolate_manager/isolate_manager.dart';
    import 'package:js/js.dart' as pjs;
    import 'package:js/js_util.dart' as js_util;
    
    @pjs.JS('self')
    external dynamic get globalScopeSelf;
    
    /// ============================================
    /// dart compile js worker.dart -o worker.js -O4
    /// ============================================
    
    /// TODO: Mapping between your `workerFunction` and real `Function`
    Map<String, Function> map = {
      // 'add': add,
    };
    
    /// In most cases you don't need to modify this function
    main() {
      callbackToStream('onmessage', (html.MessageEvent e) {
        return js_util.getProperty(e, 'data');
      }).listen((message) async {
        final Completer completer = Completer();
        completer.future.then(
          (value) => jsSendMessage(value),
          onError: (err, stack) =>
              jsSendMessage(IsolateException(err, stack).toJson()),
        );
        try {
          final function = map[message[0]] as Function;
          final params = message[1];
          completer.complete(function(params));
        } catch (err, stack) {
          jsSendMessage(IsolateException(err, stack).toJson());
        }
      });
    }
    
    /// Internal function
    Stream<T> callbackToStream<J, T>(
        String name, T Function(J jsValue) unwrapValue) {
      var controller = StreamController<T>.broadcast(sync: true);
      js_util.setProperty(js.context['self'], name, js.allowInterop((J event) {
        controller.add(unwrapValue(event));
      }));
      return controller.stream;
    }
    
    /// Internal function
    void jsSendMessage(dynamic m) {
      js.context.callMethod('postMessage', [m]);
    }
    
    
  • Step 2 Modify the mapping between your functionName and real function:

    /// TODO: Mapping between your `workerFunction` and real `Function`
    Map<String, Function> map = {
      // 'add': add,
    };
    

You should copy that functions to separated file or copy to worker.dart file to prevent the dart compile js error because some other functions depend on flutter library.

  • Step 3: Run dart compile js worker.dart -o worker.js -O4 to compile dart to js (-O0 to -O4 is the obfuscated level of js).

  • Step 4: Copy worker.js to web folder (the same folder with index.html).

  • Step 5: Now you can add worker to worker parameter like below:

    final isolates = IsolatesHelper(
      concurrent: 3,
      worker: 'worker',
      isDebug: true,
    );
    
  • Step 6 Here is the way to execute a Worker function

    final result = await isolates(
      // Here is the normal function
      add, 
    
      // Here is the normal params
      [2, 3], 
    
      // Here is the name of the function that is mapped in the step 2
      workerFunction: 'add',
        
      // [Optional] the normal params will be used if this value is null
      workerParams: [2, 3], 
      );
    

Contributions #

If you encounter any problems or feel the library is missing a feature, feel free to open an issue. Pull requests are also welcome.

Donations #

If you like my work or the free stuff on this channel and want to say thanks, or encourage me to do more, you can buy me a coffee. Thank you so much!

PayPal

7
likes
0
pub points
61%
popularity

Publisher

verified publisherlamnhan.dev

An easy way to create multiple long live isolates for computation, support try-catch block.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

isolate_manager

More

Packages that depend on isolates_helper