From 0080d1dff081e2a40f74fa16161768c58f3251a0 Mon Sep 17 00:00:00 2001 From: Leo Horie Date: Fri, 2 Dec 2016 17:42:34 -0500 Subject: [PATCH] fix request redrawing semantics --- request/request.js | 50 ++++++++++++++++++++--------------- request/tests/test-request.js | 38 ++++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 24 deletions(-) diff --git a/request/request.js b/request/request.js index a005f240..91bc55cd 100644 --- a/request/request.js +++ b/request/request.js @@ -5,33 +5,36 @@ var buildQueryString = require("../querystring/build") module.exports = function($window, Promise) { var callbackCount = 0 - var count = 0 var oncompletion function setCompletionCallback(callback) {oncompletion = callback} - function complete() {if (--count === 0 && typeof oncompletion === "function") oncompletion()} + function finalizer() { + var count = 0 + function complete() {if (--count === 0 && typeof oncompletion === "function") oncompletion()} - function finalize(promise) { - var then = promise.then - promise.then = function() { - count++ - var next = then.apply(promise, arguments) - next.then(complete, function(e) { - complete() - throw e - }) - return finalize(next) + return function finalize(promise) { + var then = promise.then, catcher = promise.catch + promise.then = function() { + count++ + var next = then.apply(promise, arguments) + next.then(complete, function(e) { + complete() + throw e + }) + return finalize(next) + } + return promise } - return promise } function request(args, extra) { - return finalize(new Promise(function(resolve, reject) { - if (typeof args === "string") { - var url = args - args = extra || {} - if (args.url == null) args.url = url - } + var finalize = finalizer() + if (typeof args === "string") { + var url = args + args = extra || {} + if (args.url == null) args.url = url + } + var promise = new Promise(function(resolve, reject) { if (args.method == null) args.method = "GET" args.method = args.method.toUpperCase() @@ -79,11 +82,13 @@ module.exports = function($window, Promise) { if (useBody && (args.data != null)) xhr.send(args.data) else xhr.send() - })) + }) + return args.redraw === false ? promise : finalize(promise) } function jsonp(args) { - return finalize(new Promise(function(resolve, reject) { + var finalize = finalizer() + var promise = new Promise(function(resolve, reject) { var callbackName = args.callbackName || "_mithril_" + Math.round(Math.random() * 1e16) + "_" + callbackCount++ var script = $window.document.createElement("script") $window[callbackName] = function(data) { @@ -101,7 +106,8 @@ module.exports = function($window, Promise) { args.data[args.callbackKey || "callback"] = callbackName script.src = assemble(args.url, args.data) $window.document.documentElement.appendChild(script) - })) + }) + return args.redraw === false? promise : finalize(promise) } function interpolate(url, data) { diff --git a/request/tests/test-request.js b/request/tests/test-request.js index 272acd73..7ddc4325 100644 --- a/request/tests/test-request.js +++ b/request/tests/test-request.js @@ -6,10 +6,13 @@ var Request = require("../../request/request") var Promise = require("../../promise/promise") o.spec("xhr", function() { - var mock, xhr + var mock, xhr, complete o.beforeEach(function() { mock = xhrMock() - xhr = new Request(mock, Promise).request + var requestService = Request(mock, Promise) + xhr = requestService.request + complete = o.spy() + requestService.setCompletionCallback(complete) }) o.spec("success", function() { @@ -295,6 +298,37 @@ o.spec("xhr", function() { o(typeof xhr.send).equals("function") } }) + o("requests don't block each other", function(done) { + mock.$defineRoutes({ + "GET /item": function(request) { + return {status: 200, responseText: "[]"} + } + }) + xhr("/item").then(function() { + return xhr("/item") + }) + xhr("/item").then(function() { + return xhr("/item") + }) + setTimeout(function() { + o(complete.callCount).equals(4) + done() + }, 20) + }) + o("requests trigger finally once with a chained then", function(done) { + mock.$defineRoutes({ + "GET /item": function(request) { + return {status: 200, responseText: "[]"} + } + }) + var promise = xhr("/item") + promise.then(function() {}).then(function() {}) + promise.then(function() {}).then(function() {}) + setTimeout(function() { + o(complete.callCount).equals(1) + done() + }, 20) + }) }) o.spec("failure", function() { o("rejects on server error", function(done) {