Dart HttpClient.getURL, вызываемый таймером без клиента или http-сервера

#dart #server-side #dart-async

#dart #на стороне сервера #dart-асинхронный

Вопрос:

РЕДАКТИРОВАТЬ: проблема не была связана с таймером или HTTPServer, это было dart.io функция сна приостанавливает все. Это четко описано в документации, мой плохой.

//

У меня странная проблема с HttpClient, работающим в коде сервера. Я вызываю

 client.getUrl(Uri.parse(url)).then((HttpClientRequest response) => response.close()).then(HttpBodyHandler.processResponse).then((HttpClientResponseBody body) {
    print(body.response.statusCode);
 

из объекта Timer, и он никогда не достигает шага печати.
Это почти копирование и вставка кода из предыдущей версии, которая вызывалась не из Timer, а из HttpRequest. Рабочий код находится в моем вопросе [здесь] [1].
В длинной строке происходит сбой, я подозреваю, что это последнее будущее, которого он никогда не достигнет (HttpClientResponseBody).

Объект Timer создается следующим образом (просто тестовый код):

 main() {
  t = new Timer.periodic(new Duration(minutes: period), (Timer t) => hit());

}

void hit() {
  if (new DateTime.now().hour == 17) {
    print("syncing rock");

    loadUrlBody(furl   filter).then((content) {
      print("content loaded");
 

//редактировать:
хорошо, вот источник, это может быть какая-то тривиальная проблема .. которую я не могу решить в течение двух дней:-D

 import 'dart:async';
import 'dart:io';
import 'package:http_server/http_server.dart';
import 'package:slack/slack_io.dart' as slack;

Timer t;
bool check;
final period = 1;
final furl = "https://****.tpondemand.com";
final filter = "somefilter";


main() {
  t = new Timer.periodic(new Duration(minutes: period), (Timer t) => hit());

}

void hit() {
  if (new DateTime.now().hour == 17) {
    print("syncing rock");

    loadUrlBody(furl   filter).then((content) {
      print("content loaded");
      Map parsedMap = content.body;
      handleMap(parsedMap);
    });
    sleep(new Duration(minutes: 60));
  } else {
    print("no time to rock "   new DateTime.now().toString());
    sleep(new Duration(minutes: period * 10));
  }
}

Future loadUrlBody(String url) {
  final c = new Completer();
  HttpClient client = new HttpClient();
  client.addCredentials(Uri.parse("https://****.tpondemand.com/api"), "tprealm", new HttpClientBasicCredentials("user", "password"));
  client.getUrl(Uri.parse(url)).then((HttpClientRequest response) => response.close()).then(HttpBodyHandler.processResponse).then((HttpClientResponseBody body) {
    print(body.response.statusCode);
    c.complete(body);
  });
  return c.future;
}



void send2Slack(String m) {
  slack.Message message = new slack.Message()..text = m;

  slack.token = 'token';
  slack.team = 'team';
  slack.send(message);
}
void handleMap(Map valueMap) {

  final Duration lostInTime = new Duration(days: 30);
  var sb = new StringBuffer();
  sb.write('K o m p o s t n');

  for (var item in valueMap["Items"]) {
    if (item['CreateDate'] == null) item['CreateDate'] = '/Date(1403167885000 0100)/';
    if (item['ModifyDate'] == null) item['ModifyDate'] = '/Date(1403167885000 0100)/';
    if (item['LastCommentDate'] == null) item['LastCommentDate'] = '/Date(1403167885000 0100)/';

    DateTime moonLanding = new DateTime.fromMillisecondsSinceEpoch(int.parse(item['CreateDate'].substring(6, 19)));
    DateTime modifyLanding = new DateTime.fromMillisecondsSinceEpoch(int.parse(item['ModifyDate'].substring(6, 19)));
    DateTime commentLanding = new DateTime.fromMillisecondsSinceEpoch(int.parse(item['LastCommentDate'].substring(6, 19)));
    DateTime lastChangeLanding = (modifyLanding.isBefore(commentLanding)) ? commentLanding : modifyLanding;
    Duration difference = new DateTime.now().difference(lastChangeLanding);

    if (moonLanding.add(lostInTime).isBefore(new DateTime.now()) amp;amp; difference.inDays > 4) {
      sb
          ..write('<https://****.tpondemand.com/entity/')
          ..write(item['Id'])
          ..write('|')
          ..write(item['Name'])
          ..write('> last change: ')
          ..write(difference.inDays)
          ..write(' days ago n');

    }
    ;


  }
  send2Slack(sb.toString());
  print("sent to Slack");
  sb.clear();
}
 

Комментарии:

1. Ваши фрагменты кода кажутся немного несвязанными. Можете ли вы создать минимальный пример кода, позволяющий воспроизвести проблему? Вы пишете getUrl из Timer , не работает, но вы вызываете hit() из Timer . Я предполагаю, что вы забыли какой return -то или аналогичный простой недосмотр, но трудно определить форму вашего кода.

2. Обновленный код намного лучше, но вы должны были сократить его до минимума, который позволяет воспроизвести проблему. Как вы думаете handleMap , и send2Slack связаны с вашей проблемой? Где определение sleep . Вам действительно следует попытаться сократить свой код так, чтобы остался минимальный объем кода, необходимый для воспроизведения вашей проблемы. В большинстве случаев это само по себе выявляет причину проблемы.

3. хорошо, работая над этим, кажется, что спящий режим замораживает все процессы, и это вызвало замораживание запроса в середине 🙂

4. Можете ли вы добавить реализацию sleep() к вашему вопросу? sleep кажется странным. Я думаю, вы пытаетесь сделать что-то, что плохо работает в Dart. Dart не предоставляет что-то похожее sleep на себя, потому что оно плохо вписывается в модель асинхронного программирования. Я думаю, вам понадобится другой подход. Если я смогу взглянуть на ваш код, я мог бы внести предложение.

Ответ №1:

Я создал аналогичный код, но не могу воспроизвести вашу проблему.
Так что в основном это работает при вызове из a Timer .

 import 'dart:io';
import 'dart:async';
import 'package:http_server/http_server.dart';

Timer t;
final period = 1;

void main(args) {
  t = new Timer.periodic(new Duration(minutes: period), (Timer t) => hit());
}

void hit() {
  loadUrlBody('http://www.google.com')
      .then((HttpClientResponseBody b) => print('hit: ${b.response.statusCode}'));
}

Future loadUrlBody(String url) {
  print('executing');
  HttpClient client = new HttpClient();
  // commented out because I have no server where I can use it
  // HttpClient client = new HttpClient()              
  //    ..addCredentials(Uri.parse("https://****.tpondemand.com/api"), "tprealm", new HttpClientBasicCredentials("user", "password"));
  return client.getUrl(Uri.parse(url))        // <== return is important here
      .then((HttpClientRequest response) => response.close())
      .then(HttpBodyHandler.processResponse)
      .then((HttpClientResponseBody body) {
        print('body: (${new DateTime.now()}) ${body.response.statusCode}');
        return body;                         // <== this value is the value the next 'then' receives. 
// for example x in: loadUrlBody('http://someurl').then(x) => doSomething(x)); 
      });
}
 

Вам не нужно использовать Completer . Completer предназначены для более сложных используемых случаев, когда, например, один метод возвращает завершитель, и, например, обработчик событий завершает его.

Вам просто нужно убедиться, что вы возвращаете Future везде. then всегда возвращает a Future . Возвращаемое значение — Future это значение, возвращаемое внутри then .

Комментарии:

1. Спасибо за упрощение моего кода, я неправильно понял концепцию Completer . Моя проблема была связана с функцией сна, я думал, что Будущее — это своего рода нить, но это не так, и сон приостановил ее.

2. An Isolate больше всего похож на нить в Dart. Future речь идет об асинхронном программировании. Это означает, что пока какой-то код ожидает ответа (например, операция ввода-вывода, делегированная операционной системе), может выполняться другой код. Это модель разделения времени. Весь код в одном изоляте выполняется на одном ядре процессора. Future также может рассматриваться как более простой API для обратных вызовов.