diff --git a/MANIFEST b/MANIFEST index f72a486..9fc6414 100644 --- a/MANIFEST +++ b/MANIFEST @@ -3,6 +3,8 @@ LICENSE MANIFEST Makefile.PL README.md +await.pl +await_simple.pl lib/Promise/ES6.pm lib/Promise/ES6/AnyEvent.pm lib/Promise/ES6/Backend/PP.pm @@ -17,6 +19,7 @@ t/all.t t/all_async.t t/allsettled.t t/anyevent.t +t/async_await.t t/await.t t/await_then_with_async.t t/await_with_async.t diff --git a/await.pl b/await.pl new file mode 100755 index 0000000..ee06d65 --- /dev/null +++ b/await.pl @@ -0,0 +1,68 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + +use experimental 'signatures'; + +use FindBin; +use lib "$FindBin::Bin/lib"; +use Promise::ES6; + +use blib "$FindBin::Bin/Future-AsyncAwait-0.47"; + +use Future::AsyncAwait future_class => 'Promise::ES6'; + +use IO::Async::Loop; +use IO::Async::Timer::Countdown; + +sub delay ($loop, $secs) { + return Promise::ES6->new( sub ($res, @) { + my $timer; $timer = IO::Async::Timer::Countdown->new( + delay => $secs, + on_expire => sub { + undef $timer; + $res->($secs); + }, + ); + + $timer->start(); + $loop->add($timer); + } ); +} + +async sub thethings ($loop) { + print "waiting …\n"; + + my $waited_p = delay($loop, 0.2); + + my $waited = await $waited_p; + + print "waited $waited\n"; + + return 5; +} + +#sub thethings_plain { +# print "waiting …\n"; +# return delay(3.2)->then( sub ($val) { +# print "waited $val\n"; +# 5; +# } ); +#} + +my $loop = IO::Async::Loop->new(); +Promise::ES6::use_event('IO::Async', $loop); + +# It works thus: +#my $promise1 = thethings($loop); +#my $promise = $promise1->then( sub ($val) { + +my $promise = thethings($loop)->then( sub ($val) { + print "async gave $val\n"; + $loop->stop(); +} ); + +$loop->run(); + +1; diff --git a/await_simple.pl b/await_simple.pl new file mode 100755 index 0000000..93f4d8d --- /dev/null +++ b/await_simple.pl @@ -0,0 +1,30 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + +use FindBin; +use lib "$FindBin::Bin/lib"; +use Promise::ES6; + +use Time::HiRes; + +#use blib "$FindBin::Bin/Future-AsyncAwait-0.47"; + +use Future::AsyncAwait future_class => 'Promise::ES6'; + +my $resolver_cr; +my $p = Promise::ES6->new( sub { $resolver_cr = shift } ); + +async sub do_await { + my $p = shift; + return await $p; +} + +do_await($p)->then( sub { print "got " . shift . $/ } ); + +Time::HiRes::sleep(0.1); + +$resolver_cr->(5); + +1; diff --git a/lib/Promise/ES6/Backend/PP.pm b/lib/Promise/ES6/Backend/PP.pm index 6711586..6b07bda 100644 --- a/lib/Promise/ES6/Backend/PP.pm +++ b/lib/Promise/ES6/Backend/PP.pm @@ -334,4 +334,53 @@ sub DESTROY { } } +#---------------------------------------------------------------------- + +# Future::AsyncAwait::Awaitable interface: + +sub AWAIT_NEW_DONE { + (ref($_[0]) || $_[0])->resolve( $_[1] ); +} + +sub AWAIT_NEW_FAIL { + (ref($_[0]) || $_[0])->reject( $_[1] ); +} + +sub AWAIT_CLONE { + (ref $_[0])->new(\&_noop); +} + +sub AWAIT_DONE { + my $copy = $_[1]; + + $_[0]->_settle(bless \$copy, _RESOLUTION_CLASS); +} + +sub AWAIT_FAIL { + my $copy = $_[1]; + + $_[0]->_settle(bless \$copy, _REJECTION_CLASS); +} + +sub AWAIT_IS_READY { + !UNIVERSAL::isa( $_[0]->[_VALUE_SR_IDX], _PENDING_CLASS ); +} + +sub AWAIT_IS_CANCELLED { 0 } + +sub AWAIT_GET { + return ${ $_[0]->[_VALUE_SR_IDX] } if UNIVERSAL::isa( $_[0]->[_VALUE_SR_IDX], _RESOLUTION_CLASS ); + + die ${ $_[0]->[_VALUE_SR_IDX] }; +} + +sub _noop {} + +sub AWAIT_ON_READY { + $_[0]->finally($_[1])->catch(\&noop); +} + +sub AWAIT_CHAIN_CANCEL { } +sub AWAIT_ON_CANCEL { } + 1; diff --git a/t/async_await.t b/t/async_await.t new file mode 100644 index 0000000..036ce7d --- /dev/null +++ b/t/async_await.t @@ -0,0 +1,27 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + +use Test::More; + +# This test throws unhandled-rejection warnings … do they matter? +#use Test::FailWarnings; + +my $failed_why; + +BEGIN { + eval 'use Test::Future::AsyncAwait::Awaitable; 1' or $failed_why = $@; +} + +plan skip_all => "Can’t run test: $failed_why" if $failed_why; + +use Promise::ES6; + +Test::Future::AsyncAwait::Awaitable::test_awaitable( + 'Promise::ES6 conforms to Awaitable API', + class => 'Promise::ES6', + new => sub { Promise::ES6->new( sub {} ) }, +); + +done_testing;