2014-01-31 39 views
0

我正在學習dart並創建了一個簡單的聯繫表單 - 基於飛鏢網站上的表單教程,使用郵件發送郵件。Dart郵件程序向客戶端返回成功或錯誤

到目前爲止這麼好 - 客戶發佈消息,服務器提取發佈數據,創建信封併發送郵件......但我想向填寫表單的人顯示一條令人欣慰的消息,或者警告他們,如果它沒有發送。

的問題是,HTTP響應是,發送電子郵件完成未來之前發送 -

有關使用完成者來解決這個問題克里斯風暴會談,我想 - 在這裏:testing error conditions with 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 = '[email protected]' //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 = ['[email protected]'] 
    ..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 

} 
+0

我想你應該添加代碼如何處理傳入的請求來自客戶。 –

回答

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; 

而且因爲你正在返回一個Future,你必須改變你的客戶送你的迴應,從

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

sendMail(postData) 
    .then((result) { 
    res.write(result); 
    res.close(); 
    }); 
+0

就是這樣!返回運輸。發送(信封)就足夠了,而不需要導入異步庫並使用完成者 - 之前當我試圖這樣做時,我得到了'未來的實例'作爲結果 - 沒有意識到未來可以被接受爲回報 - 改變向客戶發送回覆的方式是缺失的 - 現在我知道如何處理未來的回報,謝謝! – theTechnaddict

0

您的代碼不看壞:)

至於我可以看到有沒有丟失太多(沒有嘗試過,雖然執行它)。

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

無論是在handlePost()(你有req可用或
回報,你想從handlePost()返回給客戶端gotMessage(),並添加以上線路出現的結果。

而且看看An Introduction to the dart:io Library - Writing web servers

+0

感謝您的回覆 - 我可以發送回覆 - 我無法發送正確的回覆 - 取決於transport.send(信封)的結果 - 進一步調查後,問題與時間有關 - 未來返回一個值(.then)我可以調用一個函數(而不是像上面那樣打印),但發生在其他事情發生後 - 即使我設置了一個頂級變量並在該函數中設置了值,什麼是寫入請求響應的是初始值,而不是在未來完成之前寫入響應的新值。 – theTechnaddict

+0

明天我會再看一遍,在這裏是午夜和時間睡覺:o –

+0

謝謝 - 我已經編輯了問題和代碼以使事情更清楚。我想我在同一時區 - 我的睡前時間也過去了! – theTechnaddict