dart系列之:瀏覽器中的舞者,用dart傳送HTTP請求

flydean發表於2021-12-15

簡介

dart:html包為dart提供了構建瀏覽器客戶端的一些必須的元件,之前我們提到了HTML和DOM的操作,除了這些之外,我們在瀏覽器端另一個常用的操作就是使用XMLHttpRequest去做非同步HTTP資源的請求,也就是AJAX請求。

dart同樣提供了類似JS中XMLHttpRequest的封裝,其對應的類叫做HttpRequest,一起來看看在dart中怎麼使用HttpRequest吧。

傳送GET請求

雖然現代的web APP被各種框架所封裝,但是歸根結底他還是一個AJAX的富客戶端應用。我們通過各種非同步的HTTP請求向伺服器端請求資料,然後展示在頁面上。一般來說資料的互動格式是JSON,當然也可以有其他的資料互動格式。

AJAX中最常用的方式就是向伺服器端傳送get請求,對應的HttpRequest有一個getString方法:

  static Future<String> getString(String url,
      {bool? withCredentials, void onProgress(ProgressEvent e)?}) {
    return request(url,
            withCredentials: withCredentials, onProgress: onProgress)
        .then((HttpRequest xhr) => xhr.responseText!);
  }

注意,getString方法是一個類方法,所以直接使用HttpRequest類來呼叫:

var name = Uri.encodeQueryComponent('John');
        var id = Uri.encodeQueryComponent('42');
        HttpRequest.getString('users.json?name=$name&id=$id')
          .then((String resp) {
            // Do something with the response.
        });

因為getString返回的是一個Future,所以可以直接在getString後面接then語句,來獲取返回的值。

當然,你也可以在async方法中使用await來獲取返回值。

Future<void> main() async {
  String pageHtml = await HttpRequest.getString(url);
  // Do something with pageHtml...
}

或者使用try catch來捕獲異常:

try {
  var data = await HttpRequest.getString(jsonUri);
  // Process data...
} catch (e) {
  // Handle exception...
}

傳送post請求

GET是從伺服器拉取資料,相應的POST就是通用的向伺服器中提交資料的方法。在HttpRequest中,對應的方法是postFormData:

static Future<HttpRequest> postFormData(String url, Map<String, String> data,
      {bool? withCredentials,
      String? responseType,
      Map<String, String>? requestHeaders,
      void onProgress(ProgressEvent e)?}) {
    var parts = [];
    data.forEach((key, value) {
      parts.add('${Uri.encodeQueryComponent(key)}='
          '${Uri.encodeQueryComponent(value)}');
    });
    var formData = parts.join('&');

    if (requestHeaders == null) {
      requestHeaders = <String, String>{};
    }
    requestHeaders.putIfAbsent('Content-Type',
        () => 'application/x-www-form-urlencoded; charset=UTF-8');

    return request(url,
        method: 'POST',
        withCredentials: withCredentials,
        responseType: responseType,
        requestHeaders: requestHeaders,
        sendData: formData,
        onProgress: onProgress);
  }

從方法的實現上可以看到,預設情況下使用的Content-Type: application/x-www-form-urlencoded; charset=UTF-8, 也就是說預設是以form表單提交的形式進行的。

在這種情況下,對於承載資料的data來說,會首先進行Uri.encodeQueryComponent進行編碼,然後再使用&進行連線。

下面是使用的例子:

var data = { 'firstName' : 'John', 'lastName' : 'Doe' };
        HttpRequest.postFormData('/send', data).then((HttpRequest resp) {
          // Do something with the response.
       });
注意,postFormData中返回的是一個HttpRequest,雖然它叫做Request,但是實際上可以包含response的內容。所以直接使用他獲取返回內容即可。

更加通用的操作

上面我們講解了get和form的post,從程式碼可以看到,他們底層實際上都呼叫的是request方法。request是一個更加通用的HTTP請求方法。可以支援POST, PUT, DELETE等HTTP操作。下面是request的方法定義:

  static Future<HttpRequest> request(String url,
      {String? method,
      bool? withCredentials,
      String? responseType,
      String? mimeType,
      Map<String, String>? requestHeaders,
      sendData,
      void onProgress(ProgressEvent e)?})

其中sendData可以是[ByteBuffer],[Blob], [Document], [String], 或者 [FormData] 等格式。

responseType表示的是HttpRequest.responseType,是返回物件的格式,預設情況下是String,也可以是'arraybuffer', 'blob', 'document', 'json', 或者 'text'。

下面是一個是直接使用request的例子:

        var myForm = querySelector('form#myForm');
        var data = new FormData(myForm);
        HttpRequest.request('/submit', method: 'POST', sendData: data)
          .then((HttpRequest resp) {
            // Do something with the response.
        });

總結

使用HttpRequest可以直接模擬瀏覽器中的Ajax操作,非常方便。

本文已收錄於 http://www.flydean.com/21-dart-http/

最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!

歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!

相關文章