我正在学习 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
}