Size: a a a

2020 December 16

a

allter in Modern::Perl
Warstone
Эм... Окей... Чуть изменим сигнатуру...
Я кажется понял, к чему вы ведёте.
Для того, что бы добиться идеальной композабельности, надо как раз перейти на полностью функциональные алгоритмы и структуры данных. Т.е. от промисов к Task/IO, а от них - к функциональным стримам.
источник

W

Warstone in Modern::Perl
А теперь по русски. А лучше - кодом.
источник

W

Warstone in Modern::Perl
Так как слишком много умных слов
источник

W

Warstone in Modern::Perl
Но задача написать это на промисах, а не на Task/IO
источник

W

Warstone in Modern::Perl
А вот код на коллбеках, кстати:
sub get {
 my ($on_complete) = @_;
 my $list = [];
 HTTP::Request->request("http://127.0.0.1", my $chunk_work = sub {
   my ($result) = @_;
   push(@$list, @{$result->json->{data}});
   if(my $page = $result->json->{next}) {
     HTTP::Request->request("http://127.0.0.1?page=$page", $chunk_work);
   } else {
     $on_complete->($list);
   }
 });
}
источник

W

Warstone in Modern::Perl
Тоже довольно лаконично, как по мне, но нету явного цикла. Поэтому он хуже чем a/a версия. Читабельности нету.
источник

a

allter in Modern::Perl
Warstone
sub get: Async {
 my $list = [];
 my $data = await HTTP::Request->request("http://127.0.0.1");
 push(@$list, @{$data->json->{data}});
 while(my $page = $data->json->{next}) {
   $data = await HTTP::Request->request("http://127.0.0.1?page=$page");
   push(@$list, @{$data->json->{data}});
 }
 return $list;
}
```

sub get {
 my $list = [];
 my $get_chunk;
 $get_chunk = sub { my $url = shift;
   HTTP::Request->request($url)->then( sub { my $data = shift;
     push(@$list, @{$data->json->{data}});
     if ( my $page = $data->json->{next} ) {
       $get_chunk->( "http://127.0.0.1?page=$page" );
     } else {
       undef;
     }
   } );
 };
  my $promise = $get_chunk->( "http://127.0.0.1" );
  $promise->then( sub { return $list; } );
}


```
источник

W

Warstone in Modern::Perl
Это не сработает.
источник

W

Warstone in Modern::Perl
У вас в $list будет только первая страница
источник

a

allter in Modern::Perl
в mojo (я про него ничего не знаю)? почему бы это?
источник

W

Warstone in Modern::Perl
Нет, в любом случае
источник

W

Warstone in Modern::Perl
Хотя минуту...
источник

a

allter in Modern::Perl
Warstone
У вас в $list будет только первая страница
нет. Коллбэк в
 $promise->then( sub { return $list; } ); 
вызовется только когда $page больше не будет
источник

a

allter in Modern::Perl
Но я в общем-то и не противоречу, что с async/await код чище и понятнее (иначе бы не написал свою либу для сахара).
источник

a

allter in Modern::Perl
Реально, промисов действительно недостаточно. Но их станет недостаточно как раз когда вы начнёте обрабатывать ошибки и таймауты. Для этого вам потребуются IO/Stream, либо вы будете вынуждены некрасиво добавлять всякие штуки типа AbortController.
источник

AK

Andrey Karepin in Modern::Perl
Warstone
Ну а на a/a это было-бы в разы проще. Чтение с пагинацией:
var request = construct_my_request();
List<result> results = new List<result>();
var request_results;
int page_num = 0;
do {
   request_results = await request.Invoke(page_num++);
   results.Add(request_results);
} while(request_results.Count == PAGE_LIMIT);
а не проще добавить отдельный endpoint который будет возвращать ВСЕ ДАННЫЕ, а не городить костыли с порциональным вычитыванием всех данных?
источник

W

Warstone in Modern::Perl
allter
нет. Коллбэк в
 $promise->then( sub { return $list; } ); 
вызовется только когда $page больше не будет
Да, за чет того что then, в случае если ему вернули промис, будет его дожидаться... Но это вроде не так давно появилось или я путаю?
источник

IB

Ivan Bessarabov in Modern::Perl
Andrey Karepin
а не проще добавить отдельный endpoint который будет возвращать ВСЕ ДАННЫЕ, а не городить костыли с порциональным вычитыванием всех данных?
1. Иногда ты получаешь API как данность и ты не можешь управлять тем как оно работает
2. Пагинация — это очень правильное решение во очеь большом количестве ситуаций. Данные имеют обыкновения все увеличиваться и увеличиваться и без пагинации в конце концов endpoint перестанет работать.
источник

W

Warstone in Modern::Perl
Andrey Karepin
а не проще добавить отдельный endpoint который будет возвращать ВСЕ ДАННЫЕ, а не городить костыли с порциональным вычитыванием всех данных?
Внешнее API
источник

a

allter in Modern::Perl
Warstone
Да, за чет того что then, в случае если ему вернули промис, будет его дожидаться... Но это вроде не так давно появилось или я путаю?
Он и не будет дожидаться. Колбэк в then выполнится (асинхронно), когда заресолвится промис, на который он навешен.
Например, если произойдёт ошибка получения на любом шаге, он вообще не вызовется, (а get() заресолвится в ошибку).
источник