Module: Ione::Future::Combinators

Included in:
Ione::Future
Defined in:
lib/ione/future.rb

Overview

Since:

  • v1.0.0

Instance Method Summary collapse

Instance Method Details

#fallback {|error| ... } ⇒ Ione::Future

Returns a new future which represents either the value of the original future, or the value of the future returned by the given block.

This is like #recover but for cases when the handling of an error is itself asynchronous. In other words, #fallback is to #recover what #flat_map is to #map.

If the block raises an error a failed future with that error will be returned (this can be used to transform an error into another error, instead of tranforming an error into a value).

Examples:

result = http_get('/foo/bar').fallback do |error|
  http_get('/baz')
end
result.value # either the response to /foo/bar, or if that failed
             # the response to /baz

Yield Parameters:

  • error (Object)

    the error from the original future

Yield Returns:

  • (Object)

    the value of the new future

Returns:

  • (Ione::Future)

    a new future representing a value recovered from the error

Since:

  • v1.0.0


542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
# File 'lib/ione/future.rb', line 542

def fallback(&block)
  f = CompletableFuture.new
  on_complete do |v, e|
    if e
      begin
        ff = block.call(e)
        ff.on_complete do |vv, ee|
          if ee
            f.fail(ee)
          else
            f.resolve(vv)
          end
        end
      rescue => e
        f.fail(e)
      end
    else
      f.resolve(v)
    end
  end
  f
end

#flat_map {|value| ... } ⇒ Ione::Future

Returns a new future representing a transformation of this future's value, but where the transformation itself may be asynchronous.

This method is useful when you want to chain asynchronous operations.

Examples:

future2 = future1.flat_map { |value| method_returning_a_future(value) }

Yield Parameters:

  • value (Object)

    the value of this future

Yield Returns:

  • (Ione::Future)

    a future representing the transformed value

Returns:

  • (Ione::Future)

    a new future representing the transformed value

Since:

  • v1.0.0


411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
# File 'lib/ione/future.rb', line 411

def flat_map(&block)
  f = CompletableFuture.new
  on_complete do |v, e|
    if e
      f.fail(e)
    else
      begin
        ff = block.call(v)
        ff.on_complete do |vv, ee|
          if ee
            f.fail(ee)
          else
            f.resolve(vv)
          end
        end
      rescue => e
        f.fail(e)
      end
    end
  end
  f
end

#map(value = nil) {|value| ... } ⇒ Ione::Future

Returns a new future representing a transformation of this future's value.

Examples:

future2 = future1.map { |value| value * 2 }

Parameters:

  • value (Object) (defaults to: nil)

    the value of this future (when no block is given)

Yield Parameters:

  • value (Object)

    the value of this future

Yield Returns:

  • (Object)

    the transformed value

Returns:

  • (Ione::Future)

    a new future representing the transformed value

Since:

  • v1.0.0


384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
# File 'lib/ione/future.rb', line 384

def map(value=nil, &block)
  f = CompletableFuture.new
  on_complete do |v, e|
    if e
      f.fail(e)
    else
      begin
        f.resolve(block ? block.call(v) : value)
      rescue => e
        f.fail(e)
      end
    end
  end
  f
end

#recover(value = nil) {|error| ... } ⇒ Ione::Future

Returns a new future which represents either the value of the original future, or the result of the given block, if the original future fails.

This method is similar to #map, but is triggered by a failure. You can also think of it as a rescue block for asynchronous operations.

If the block raises an error a failed future with that error will be returned (this can be used to transform an error into another error, instead of tranforming an error into a value).

Examples:

future2 = future1.recover { |error| 'foo' }
future1.fail(error)
future2.value # => 'foo'

Parameters:

  • value (Object) (defaults to: nil)

    the value when no block is given

Yield Parameters:

  • error (Object)

    the error from the original future

Yield Returns:

  • (Object)

    the value of the new future

Returns:

  • (Ione::Future)

    a new future representing a value recovered from the error

Since:

  • v1.0.0


504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
# File 'lib/ione/future.rb', line 504

def recover(value=nil, &block)
  f = CompletableFuture.new
  on_complete do |v, e|
    if e
      begin
        f.resolve(block ? block.call(e) : value)
      rescue => e
        f.fail(e)
      end
    else
      f.resolve(v)
    end
  end
  f
end

#then {|value| ... } ⇒ Ione::Future

Returns a new future representing a transformation of this future's value, similarily to #map, but acts as #flat_map when the block returns a Ione::Future.

This method is useful when you want to transform the value of a future, but whether or not it can be done synchronously or require an asynchronous operation depends on the value of the future.

Examples:

future1 = load_something
future2 = future1.then do |result|
  if result.empty?    # make a new async call to load fallback value

    load_something_else
  else
    result
  end
end

Yield Parameters:

  • value (Object)

    the value of this future

Yield Returns:

  • (Object, Ione::Future)

    the transformed value, or a future that will resolve to the transformed value.

Returns:

  • (Ione::Future)

    a new future representing the transformed value

Since:

  • v1.2.0


458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
# File 'lib/ione/future.rb', line 458

def then(&block)
  f = CompletableFuture.new
  on_complete do |v, e|
    if e
      f.fail(e)
    else
      begin
        fv = block.call(v)
        if fv.respond_to?(:on_complete)
          fv.on_complete do |vv, ee|
            if ee
              f.fail(ee)
            else
              f.resolve(vv)
            end
          end
        else
          f.resolve(fv)
        end
      rescue => e
        f.fail(e)
      end
    end
  end
  f
end