0

我正在学习 dart 并创建了一个简单的联系表格 - 基于 dart 网站上的表格教程,使用 mailer 发送邮件。

到目前为止一切顺利 - 客户端发布消息,服务器获取发布数据,创建一个信封并发送邮件......但我想向填写表格的人显示一条令人欣慰的消息,或者如果它警告他们没有发送。

问题是在发送电子邮件的未来完成之前发送了http响应 -

Chris Storm 谈到了使用完成者来解决这个问题,我认为 - 在这里:使用 dart 测试错误条件,并在 Dart for Hipsters 的一章中再次讨论,但我发现很难弄清楚如何在这里应用它。

这是完整的服务器代码 - sendMail 函数中的注释显示了问题。

import 'dart:io';
import 'dart:convert';
import 'package:mailer/mailer.dart';

final HOST = '127.0.0.1'; // eg: localhost
final PORT = 4040;        // a port, must match the client program

void main() {
    HttpServer.bind(HOST, PORT).then(gotMessage, onError: printError);
}

void gotMessage(_server) {
    _server.listen((HttpRequest request) {
    switch (request.method) {
      case 'POST':
        handlePost(request);
        break;
     case 'OPTIONS':
        handleOptions(request);
        break;
     default: defaultHandler(request);
     }
   },
  onError: printError); // .listen failed
  print('Listening for GET and POST on http://$HOST:$PORT');
}

/**
 * Handle POST requests
 *
 */


void handlePost(HttpRequest req) {
  HttpResponse res = req.response;
  print('${req.method}: ${req.uri.path}');

  addCorsHeaders(res);

  req.listen((List<int> buffer) {
     // Create a new string from the characters in the buffer and convert this into a map
    Map postData = JSON.decode(new String.fromCharCodes(buffer));
    res.write(sendMail(postData));
    res.close();
  },

  onError: printError);
}

/**
 * Add Cross-site headers to enable accessing this server from pages
 * not served by this server
 *
 * See: http://www.html5rocks.com/en/tutorials/cors/
 * and http://enable-cors.org/server.html
 */
void addCorsHeaders(HttpResponse res) {
  res.headers.add('Access-Control-Allow-Origin', '*, ');
  res.headers.add('Access-Control-Allow-Methods', 'POST, OPTIONS');
  res.headers.add('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
}

void handleOptions(HttpRequest req) {
  HttpResponse res = req.response;
  addCorsHeaders(res);
  print('${req.method}: ${req.uri.path}');
  res.statusCode = HttpStatus.NO_CONTENT;
  res.close();
}

void defaultHandler(HttpRequest req) {
  HttpResponse res = req.response;
  addCorsHeaders(res);
  res.statusCode = HttpStatus.NOT_FOUND;
  res.write('Not found: ${req.method}, ${req.uri.path}');
  res.close();
}

void printError(error) => print(error);

sendMail(postData) {

  String sentMsg = 'I am waiting for a result to report'; //initialised value

  var options = new GmailSmtpOptions()
  ..username = 'my.mailt@gmail.com' //shove real values in here to test
  ..password = 'my_password';

  var transport = new SmtpTransport(options);

  // Create the envelope to send.
  var envelope = new Envelope()
  ..fromName = postData['name']
  ..from = postData['fromEmail']
  ..recipients = ['the_recipient@somedomain.com']
  ..subject = 'Message from contact form'
  ..text = postData['contactMessage'];


  transport.send(envelope)
    .then((success) => sentMsg = 'Message sent, thank you.' ) //this will not be returned...
    .catchError((e) => sentMsg = 'Message not sent; the reported error was: $e'); // nor will this

  return sentMsg; // Sadly the initial value will be returned as the future (transport.send) will not have completed

}
4

2 回答 2

0

你的代码看起来不错:)

据我所见,没有遗漏太多(虽然没有尝试执行它)。

  request.response.write('Hello, world'); 
  request.response.close();

要么在handlePost()(你有req可用的地方,要么
返回你想要返回给客户端的结果,handlePost()gotMessage()在那里添加上面的行。

还可以看看An Introduction to the dart:io Library - Writing web servers

于 2014-02-01T11:59:27.570 回答
0

如果我猜对了,您想根据结果发送回复transport.send()。如果是这样,您可以将其退回,例如

  return transport.send(envelope)
    .then((success) => sentMsg = 'Message sent, thank you.' )
    .catchError((e) => sentMsg = 'Message not sent; the reported error was: $e');

或使用Completer

  var c = new Completer();

  transport.send(envelope)
    .then((success) => sentMsg = 'Message sent, thank you.' )
    .then(c.complete)
    .catchError((e) => sentMsg = 'Message not sent; the reported error was: $e');

  return c.future;

而且由于您要返回 a Future,因此您必须更改将响应发送给客户的方式,从

res.write(sendMail(postData));
res.close();

sendMail(postData)
  .then((result) {
    res.write(result);
    res.close();
  });
于 2014-02-02T01:42:30.047 回答