Skip to content

Commit 5078138

Browse files
committed
Merge pull request #13 from slamdata/canceler
Add cancellation support
2 parents 8fbf208 + dfe89d2 commit 5078138

File tree

4 files changed

+35
-11
lines changed

4 files changed

+35
-11
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ Makes a `DELETE` request to the specified URL and ignores the response.
151151
#### `affjax'`
152152

153153
``` purescript
154-
affjax' :: forall e a b. (Requestable a, Responsable b) => AffjaxRequest a -> (Error -> Eff (ajax :: Ajax | e) Unit) -> (AffjaxResponse b -> Eff (ajax :: Ajax | e) Unit) -> Eff (ajax :: Ajax | e) Unit
154+
affjax' :: forall e a b. (Requestable a, Responsable b) => AffjaxRequest a -> (Error -> Eff (ajax :: Ajax | e) Unit) -> (AffjaxResponse b -> Eff (ajax :: Ajax | e) Unit) -> Eff (ajax :: Ajax | e) (Canceler (ajax :: Ajax | e))
155155
```
156156

157157
Run a request directly without using `Aff`.

bower.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"package.json"
2020
],
2121
"dependencies": {
22-
"purescript-aff": "~0.9.0",
22+
"purescript-aff": "~0.9.2",
2323
"purescript-arraybuffer-types": "~0.1.1",
2424
"purescript-dom": "~0.1.2",
2525
"purescript-foreign": "~0.4.2",

src/Network/HTTP/Affjax.purs

+29-9
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,15 @@ module Network.HTTP.Affjax
1212
, delete, delete_
1313
) where
1414

15-
import Control.Monad.Aff (Aff(), makeAff)
15+
import Control.Monad.Aff (Aff(), makeAff, makeAff', Canceler())
1616
import Control.Monad.Eff (Eff())
1717
import Control.Monad.Eff.Exception (Error(), error)
1818
import Data.Either (Either(..))
1919
import Data.Foreign (Foreign(..), F())
20-
import Data.Function (Fn4(), runFn4)
20+
import Data.Function (Fn5(), runFn5, Fn4(), runFn4)
2121
import Data.Maybe (Maybe(..), maybe)
2222
import Data.Nullable (Nullable(), toNullable)
23+
import DOM.XHR (XMLHttpRequest())
2324
import Network.HTTP.Affjax.Request
2425
import Network.HTTP.Affjax.Response
2526
import Network.HTTP.Affjax.ResponseType
@@ -66,7 +67,7 @@ type URL = String
6667

6768
-- | Makes an `Affjax` request.
6869
affjax :: forall e a b. (Requestable a, Responsable b) => AffjaxRequest a -> Affjax e b
69-
affjax = makeAff <<< affjax'
70+
affjax = makeAff' <<< affjax'
7071

7172
-- | Makes a `GET` request to the specified URL.
7273
get :: forall e a. (Responsable a) => URL -> Affjax e a
@@ -121,9 +122,9 @@ affjax' :: forall e a b. (Requestable a, Responsable b) =>
121122
AffjaxRequest a ->
122123
(Error -> Eff (ajax :: Ajax | e) Unit) ->
123124
(AffjaxResponse b -> Eff (ajax :: Ajax | e) Unit) ->
124-
Eff (ajax :: Ajax | e) Unit
125+
Eff (ajax :: Ajax | e) (Canceler (ajax :: Ajax | e))
125126
affjax' req eb cb =
126-
runFn4 unsafeAjax responseHeader req' eb cb'
127+
runFn5 _ajax responseHeader req' cancelAjax eb cb'
127128
where
128129
req' :: AjaxRequest
129130
req' = { method: methodToString req.method
@@ -149,9 +150,9 @@ type AjaxRequest =
149150
, password :: Nullable String
150151
}
151152

152-
foreign import unsafeAjax
153+
foreign import _ajax
153154
"""
154-
function unsafeAjax (mkHeader, options, errback, callback) {
155+
function _ajax (mkHeader, options, canceler, errback, callback) {
155156
return function () {
156157
var xhr = new XMLHttpRequest();
157158
xhr.open(options.method || "GET", options.url || "/", true, options.username, options.password);
@@ -179,10 +180,29 @@ foreign import unsafeAjax
179180
};
180181
xhr.responseType = options.responseType;
181182
xhr.send(options.content);
183+
return canceler(xhr);
182184
};
183185
}
184-
""" :: forall e a. Fn4 (String -> String -> ResponseHeader)
186+
""" :: forall e a. Fn5 (String -> String -> ResponseHeader)
185187
AjaxRequest
188+
(XMLHttpRequest -> Canceler (ajax :: Ajax | e))
186189
(Error -> Eff (ajax :: Ajax | e) Unit)
187190
(AffjaxResponse Foreign -> Eff (ajax :: Ajax | e) Unit)
188-
(Eff (ajax :: Ajax | e) Unit)
191+
(Eff (ajax :: Ajax | e) (Canceler (ajax :: Ajax | e)))
192+
193+
cancelAjax :: forall e. XMLHttpRequest -> Canceler (ajax :: Ajax | e)
194+
cancelAjax xhr err = makeAff (\eb cb -> runFn4 _cancelAjax xhr err eb cb)
195+
196+
foreign import _cancelAjax
197+
"""
198+
function _cancelAjax (xhr, cancelError, errback, callback) {
199+
return function () {
200+
try { xhr.abort(); } catch (e) { return errback(e)(); }
201+
return callback(true)();
202+
};
203+
};
204+
""" :: forall e. Fn4 XMLHttpRequest
205+
Error
206+
(Error -> Eff (ajax :: Ajax | e) Unit)
207+
(Boolean -> Eff (ajax :: Ajax | e) Unit)
208+
(Eff (ajax :: Ajax | e) Unit)

test/Main.purs

+4
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,7 @@ main = launchAff $ do
3737

3838
res <- attempt $ get "ttp://www.google.com"
3939
liftEff $ either traceAny (traceAny :: AffjaxResponse Foreign -> _) res
40+
41+
canceler <- forkAff (post_ "/api" "do it now")
42+
canceled <- canceler $ error "Pull the cord!"
43+
liftEff $ if canceled then (trace "Canceled") else (trace "Not Canceled")

0 commit comments

Comments
 (0)