Snippets

Matthew Schinckel 9y9MM: Untitled snippet

Created by Matthew Schinckel
/*

Wrap ajax requests in a promise.

Usage: xhr(form).then(success).catch(error);

It's also possible to call:

  var request = xhr(form).then(success).catch(error);
  request.cancel();

Which aborts the request (and rejects the promise).


You may also call xhr(a[href]).then(success).catch(error);


TODO: Look more at the cancel/abort stuff: should we reject in
      a more custom way?
*/

import {serialise} from './form';

export function xhr(form) {
  var request = new XMLHttpRequest();
  var promise = new Promise(function(resolve, reject) {
    var method = form.method || 'get',
        action,
        data,
        enctype;

    if (form.action !== undefined) {
      // We check here to see if we are doing a GET request, as
      // that requires us to open a different url, including the
      // query string. It's rather annoying that we can't get this
      // from a FormData() object, actually.
      if (method === 'get') {
        action = form.action + '?' + serialise(form);
      } else {
        action = form.action;
        data = new FormData(form);
        enctype = form.enctype || 'application/x-www-form-encoded; charset=UTF-8';
      }
    } else if (form.href) {
      action = form.href;
    }

    request.open(method, action);

    if (enctype) {
      request.setRequestHeader('Content-Encoding', enctype);
    }
    request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');

    request.onload = function() {
      if (request.status < 400) {
        resolve(new Response(request));
      } else {
        reject(new Response(request));
      }
    };

    request.onerror = function() {
      reject(new Error("Network Error"));
    };

    request.send(data);
  });
  promise.cancel = request.abort.bind(request);
  return promise;
}


function splitHeaders(string) {
  return string.split('\n').filter(Boolean).map(function(header) {
    return header.replace(/: /, '\n').split('\n');
  });
}


class Response {
  constructor (request) {
    this.statusCode = request.status;
    this.content = request.response;
    this.headers = splitHeaders(request.getAllResponseHeaders());
    this._request = request;
  }

  getHeader(header) {
    for (let hdr of this.headers) {
      if (hdr[0].toLowerCase() == header.toLowerCase()) {
        return hdr[1];
      }
    }
  }
}

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.