UNPKG

marbles

Version:

Front-end framework for routing, http, and data handling

273 lines (227 loc) 6.77 kB
"use strict"; var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { "default": obj }; }; Object.defineProperty(exports, "__esModule", { value: true }); /* @flow weak */ var _Utils = require("./utils"); var _Utils2 = _interopRequireWildcard(_Utils); var _Events = require("./events"); var _Events2 = _interopRequireWildcard(_Events); var _URI = require("./uri"); var _URI2 = _interopRequireWildcard(_URI); /** * @memberof Marbles * @class * @name Marbles.HTTPRequest * @params {Object} options * @see Marbles.HTTP */ var Request = _Utils2["default"].createClass({ displayName: "Marbles.HTTPRequest", mixins: [_Events2["default"]], willInitialize: function willInitialize(options) { if (!options) { options = {}; } this.middleware = options.middleware || []; this.method = options.method || "GET"; this.method = this.method.toUpperCase(); this.uri = new _URI2["default"](options.url, options.params || [{}]); this.requestHeaders = options.headers || {}; this.requestBody = options.body || null; if (this.method === "GET" || this.method === "HEAD") { this.id = this.method + ":" + this.uri.toString(); // the same request is already in progress if (this.constructor.activeRequests[this.id]) { return this.constructor.activeRequests[this.id]; } this.on("before:send", this.trackRequest, this); this.on("complete", this.untrackRequest, this); this.on("terminated", this.untrackRequest, this); } this.on("before:send", this.callRequestMiddleware, this); this.on("before:send", this.setXMLHTTPRequestHeaders, this); this.on("before:complete", this.callResponseMiddleware, this); this.on("complete", this.untrackRequest, this); this.on("before:send", function () { var completeResolve, completeReject; this.completePromise = new Promise(function (rs, rj) { completeResolve = rs; completeReject = rj; }); var onComplete = function onComplete(res, xhr) { this.off("terminated", onTerminated, this); this.completePromise = null; completeResolve([res, xhr]); }; var onTerminated = function onTerminated(err) { this.off("complete", onComplete, this); this.completePromise = null; completeReject(err); }; this.once("complete", onComplete, this); this.once("terminated", onTerminated, this); }, this); this.completePromise = null; }, then: function then() { var promise = this.completePromise || new Promise(function (resolve, reject) { reject(new Error("Request not started!")); }); return promise.then.apply(promise, arguments); }, "catch": function _catch() { var promise = this.completePromise || new Promise(function (resolve, reject) { reject(new Error("Request not started!")); }); return promise["catch"].apply(promise, arguments); }, setRequestHeader: function setRequestHeader(key, val) { this.requestHeaders[key] = val; }, getRequestHeader: function getRequestHeader(key) { return this.requestHeaders[key]; }, getResponseHeader: function getResponseHeader(key) { return this.xhr.getResponseHeader(key); }, terminate: function terminate(err) { this.terminated = true; this.trigger("terminated", err); }, resend: function resend(err) { this.terminate(err || "resend"); this.open(); this.send(); }, callRequestMiddleware: function callRequestMiddleware() { for (var i = 0, _ref = this.middleware, _len = _ref.length; i < _len; i++) { if (this.terminated) { break; } if (typeof _ref[i].willSendRequest === "function") { _ref[i].willSendRequest(this); } } }, callResponseMiddleware: function callResponseMiddleware() { for (var i = 0, _ref = this.middleware, _len = _ref.length; i < _len; i++) { if (this.terminated) { break; } if (typeof _ref[i].didReceiveResponse === "function") { _ref[i].didReceiveResponse(this); } } }, trackRequest: function trackRequest() { this.constructor.activeRequests[this.id] = this; }, untrackRequest: function untrackRequest() { if (this.constructor.activeRequests.hasOwnProperty(this.id)) { delete this.constructor.activeRequests[this.id]; } }, setXMLHTTPRequest: function setXMLHTTPRequest() { this.xhr = new XMLHttpRequest(); this.xhr.onreadystatechange = this.handleReadyStateChange.bind(this); }, setXMLHTTPRequestHeaders: function setXMLHTTPRequestHeaders() { for (var key in this.requestHeaders) { if (this.requestHeaders.hasOwnProperty(key)) { this.xhr.setRequestHeader(key, this.requestHeaders[key]); } } }, handleReadyStateChange: function handleReadyStateChange() { if (this.xhr.readyState !== 4) { return; } this.trigger("before:complete", this.xhr); var responseData = this.responseData || this.xhr.response; if (this.xhr.status >= 200 && this.xhr.status < 400 && this.xhr.status !== 0) { this.trigger("success", responseData, this.xhr); } else { this.trigger("failure", responseData, this.xhr); } this.trigger("complete", responseData, this.xhr); }, open: function open() { // The request is already open if (this.xhr && this.xhr.readyState !== 4) { return; } this.setXMLHTTPRequest(); var url = this.uri.toString(); var async = true; this.xhr.open(this.method, url, async); this.trigger("open", this.method, url, async); }, send: function send() { if (this.xhr.readyState !== 1) { return; } this.trigger("before:send"); try { this.xhr.send(this.requestBody); } catch (e) { setTimeout(function () { throw e; }, 0); } this.trigger("after:send"); } }); Request.activeRequests = {}; /** * @memberof Marbles * @func * @params {Object} options * @returns {Marbles.HTTPRequest} request * @see Marbles.HTTP.Middleware * @example * Marbles.HTTP({ * method: "POST", * url: "http://example.com/posts", * params: [{ * a: 1 * }], * body: { title: "My Post", content: "Lorem ipsum..." }, * middleware: [ * Marbles.HTTP.Middleware.SerializeJSON * ], * headers: { * "Content-Type": "application/json", * } * }).then(function (args) { * var res = args[0]; * var xhr = args[1]; * // request complete * // do something * }).catch(function (err) { * // request terminated * // do something * }); */ var HTTP = function HTTP(options) { var request = new Request({ method: options.method, url: options.url, params: options.params, body: options.body, headers: options.headers, middleware: options.middleware }); if (typeof options.callback === "function") { request.once("complete", options.callback); } if (!request.xhr) { request.open(); request.send(); } return request; }; exports.Request = Request; exports.HTTP = HTTP; exports["default"] = HTTP;