Skip to content

Commit f3bdc05

Browse files
authored
Merge pull request #106 from natefaubion/aff-updates
Updates for Aff 4.0
2 parents 37ae6c9 + 30eeabd commit f3bdc05

File tree

5 files changed

+72
-105
lines changed

5 files changed

+72
-105
lines changed

bower.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"package.json"
2424
],
2525
"dependencies": {
26-
"purescript-aff": "^3.0.0",
26+
"purescript-aff": "^4.0.0",
2727
"purescript-argonaut-core": "^3.0.0",
2828
"purescript-arraybuffer-types": "^1.0.0",
2929
"purescript-dom": "^4.0.0",

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"private": true,
33
"scripts": {
44
"clean": "rimraf output && rimraf .pulp-cache",
5-
"build": "eslint src && pulp build --censor-lib --strict",
5+
"build": "eslint src && pulp build -- --censor-lib --strict",
66
"test": "eslint src && pulp test"
77
},
88
"devDependencies": {

src/Network/HTTP/Affjax.js

Lines changed: 45 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@
44
/* global process */
55
"use strict";
66

7-
// module Network.HTTP.Affjax
8-
9-
// jshint maxparams: 5
10-
exports._ajax = function (mkHeader, options, canceler, errback, callback) {
7+
exports._ajax = function () {
118
var platformSpecific = { };
129
if (typeof module !== "undefined" && module.require && !(typeof process !== "undefined" && process.versions["electron"])) {
1310
// We are on node.js
@@ -42,49 +39,52 @@ exports._ajax = function (mkHeader, options, canceler, errback, callback) {
4239
};
4340
}
4441

45-
return function () {
46-
var xhr = platformSpecific.newXHR();
47-
var fixedUrl = platformSpecific.fixupUrl(options.url);
48-
xhr.open(options.method || "GET", fixedUrl, true, options.username, options.password);
49-
if (options.headers) {
50-
try {
51-
for (var i = 0, header; (header = options.headers[i]) != null; i++) {
52-
xhr.setRequestHeader(header.field, header.value);
42+
return function (mkHeader, options) {
43+
return function (errback, callback) {
44+
var xhr = platformSpecific.newXHR();
45+
var fixedUrl = platformSpecific.fixupUrl(options.url);
46+
xhr.open(options.method || "GET", fixedUrl, true, options.username, options.password);
47+
if (options.headers) {
48+
try {
49+
for (var i = 0, header; (header = options.headers[i]) != null; i++) {
50+
xhr.setRequestHeader(header.field, header.value);
51+
}
52+
} catch (e) {
53+
errback(e);
5354
}
5455
}
55-
catch (e) {
56-
errback(e)();
57-
}
58-
}
59-
xhr.onerror = function () {
60-
errback(new Error("AJAX request failed: " + options.method + " " + options.url))();
61-
};
62-
xhr.onload = function () {
63-
callback({
64-
status: xhr.status,
65-
headers: xhr.getAllResponseHeaders().split("\r\n")
66-
.filter(function (header) {
67-
return header.length > 0;
68-
})
69-
.map(function (header) {
70-
var i = header.indexOf(":");
71-
return mkHeader(header.substring(0, i))(header.substring(i + 2));
72-
}),
73-
response: platformSpecific.getResponse(xhr)
74-
})();
75-
};
76-
xhr.responseType = options.responseType;
77-
xhr.withCredentials = options.withCredentials;
78-
xhr.send(options.content);
79-
return canceler(xhr);
80-
};
81-
};
56+
xhr.onerror = function () {
57+
errback(new Error("AJAX request failed: " + options.method + " " + options.url));
58+
};
59+
xhr.onload = function () {
60+
callback({
61+
status: xhr.status,
62+
headers: xhr.getAllResponseHeaders().split("\r\n")
63+
.filter(function (header) {
64+
return header.length > 0;
65+
})
66+
.map(function (header) {
67+
var i = header.indexOf(":");
68+
return mkHeader(header.substring(0, i))(header.substring(i + 2));
69+
}),
70+
response: platformSpecific.getResponse(xhr)
71+
});
72+
};
73+
xhr.responseType = options.responseType;
74+
xhr.withCredentials = options.withCredentials;
75+
xhr.send(options.content);
8276

83-
// jshint maxparams: 4
84-
exports._cancelAjax = function (xhr, cancelError, errback, callback) {
85-
return function () {
86-
try { xhr.abort(); } catch (e) { return callback(false)(); }
87-
return callback(true)();
77+
return function (/* error */) {
78+
return function (cancelErrback, cancelCallback) {
79+
try {
80+
xhr.abort();
81+
} catch (e) {
82+
return cancelErrback(e);
83+
}
84+
return cancelCallback();
85+
};
86+
};
87+
};
8888
};
89-
};
89+
}();
9090

src/Network/HTTP/Affjax.purs

Lines changed: 18 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ module Network.HTTP.Affjax
55
, AffjaxResponse
66
, URL
77
, affjax
8-
, affjax'
98
, get
109
, post, post_, post', post_'
1110
, put, put_, put', put_'
@@ -19,21 +18,22 @@ module Network.HTTP.Affjax
1918

2019
import Prelude hiding (max)
2120

22-
import Control.Monad.Aff (Aff, makeAff, makeAff', Canceler(..), attempt, delay, forkAff, cancel)
23-
import Control.Monad.Aff.AVar (AVAR, makeVar, takeVar, putVar)
24-
import Control.Monad.Eff (kind Effect, Eff)
21+
import Control.Monad.Aff (Aff, try, delay)
22+
import Control.Monad.Aff.Compat as AC
23+
import Control.Monad.Eff (kind Effect)
2524
import Control.Monad.Eff.Class (liftEff)
2625
import Control.Monad.Eff.Exception (Error, error)
2726
import Control.Monad.Eff.Ref (REF, newRef, readRef, writeRef)
2827
import Control.Monad.Except (runExcept, throwError)
28+
import Control.Parallel (parOneOf)
2929

3030
import Data.Argonaut.Parser (jsonParser)
3131
import Data.Array as Arr
3232
import Data.Either (Either(..), either)
3333
import Data.Foldable (any)
3434
import Data.Foreign (F, Foreign, ForeignError(JSONError), fail, readString, toForeign)
3535
import Data.Function (on)
36-
import Data.Function.Uncurried (Fn5, runFn5, Fn4, runFn4)
36+
import Data.Function.Uncurried (Fn2, runFn2)
3737
import Data.HTTP.Method (Method(..), CustomMethod)
3838
import Data.HTTP.Method as Method
3939
import Data.Int (toNumber)
@@ -45,8 +45,6 @@ import Data.Tuple (Tuple(..), fst, snd)
4545

4646
import Math (max, pow)
4747

48-
import DOM.XHR.Types (XMLHttpRequest)
49-
5048
import Network.HTTP.Affjax.Request (class Requestable, RequestContent, toRequest)
5149
import Network.HTTP.Affjax.Response (class Respondable, ResponseContent, ResponseType(..), fromResponse, responseType, responseTypeToString)
5250
import Network.HTTP.RequestHeader (RequestHeader(..), requestHeaderName, requestHeaderValue)
@@ -90,10 +88,6 @@ type AffjaxResponse a =
9088
-- | Type alias for URL strings to aid readability of types.
9189
type URL = String
9290

93-
-- | Makes an `Affjax` request.
94-
affjax :: forall e a b. Requestable a => Respondable b => AffjaxRequest a -> Affjax e b
95-
affjax = makeAff' <<< affjax'
96-
9791
-- | Makes a `GET` request to the specified URL.
9892
get :: forall e a. Respondable a => URL -> Affjax e a
9993
get u = affjax $ defaultRequest { url = u }
@@ -186,23 +180,16 @@ retry
186180
:: forall e a b
187181
. Requestable a
188182
=> RetryPolicy
189-
-> (AffjaxRequest a -> Affjax (avar :: AVAR, ref :: REF | e) b)
190-
-> (AffjaxRequest a -> Affjax (avar :: AVAR, ref :: REF | e) b)
183+
-> (AffjaxRequest a -> Affjax (ref :: REF | e) b)
184+
-> (AffjaxRequest a -> Affjax (ref :: REF | e) b)
191185
retry policy run req = do
192186
-- failureRef is either an exception or a failed request
193187
failureRef <- liftEff $ newRef Nothing
194188
let loop = go failureRef
195189
case policy.timeout of
196190
Nothing -> loop 1
197191
Just timeout -> do
198-
respVar <- makeVar
199-
loopHandle <- forkAff $ loop 1 >>= putVar respVar <<< Just
200-
timeoutHandle <-
201-
forkAff $ do
202-
delay timeout
203-
putVar respVar Nothing
204-
loopHandle `cancel` error "Cancel"
205-
result <- takeVar respVar
192+
result <- parOneOf [ Just <$> loop 1, Nothing <$ delay timeout ]
206193
case result of
207194
Nothing -> do
208195
failure <- liftEff $ readRef failureRef
@@ -225,25 +212,26 @@ retry policy run req = do
225212
Right resp
226213

227214
go failureRef n = do
228-
result <- retryState <$> attempt (run req)
215+
result <- retryState <$> try (run req)
229216
case result of
230217
Left err -> do
231218
liftEff $ writeRef failureRef $ Just err
232219
delay (policy.delayCurve n)
233220
go failureRef (n + 1)
234221
Right resp -> pure resp
235222

236-
-- | Run a request directly without using `Aff`.
237-
affjax'
223+
-- | Makes an `Affjax` request.
224+
affjax
238225
:: forall e a b
239226
. Requestable a
240227
=> Respondable b
241228
=> AffjaxRequest a
242-
-> (Error -> Eff (ajax :: AJAX | e) Unit)
243-
-> (AffjaxResponse b -> Eff (ajax :: AJAX | e) Unit)
244-
-> Eff (ajax :: AJAX | e) (Canceler (ajax :: AJAX | e))
245-
affjax' req eb cb =
246-
runFn5 _ajax responseHeader req' cancelAjax eb cb'
229+
-> Affjax e b
230+
affjax req = do
231+
res <- AC.fromEffFnAff $ runFn2 _ajax responseHeader req'
232+
case res { response = _ } <$> runExcept (fromResponse' res.response) of
233+
Left err -> throwError $ error (show err)
234+
Right res' -> pure res'
247235
where
248236

249237
req' :: AjaxRequest
@@ -277,11 +265,6 @@ affjax' req eb cb =
277265
Just h | not $ any (on eq requestHeaderName h) hs -> hs `Arr.snoc` h
278266
_ -> hs
279267

280-
cb' :: AffjaxResponse ResponseContent -> Eff (ajax :: AJAX | e) Unit
281-
cb' res = case res { response = _ } <$> runExcept (fromResponse' res.response) of
282-
Left err -> eb $ error (show err)
283-
Right res' -> cb res'
284-
285268
parseJSON :: String -> F Foreign
286269
parseJSON = either (fail <<< JSONError) (pure <<< toForeign) <<< jsonParser
287270

@@ -301,20 +284,4 @@ type AjaxRequest =
301284
, withCredentials :: Boolean
302285
}
303286

304-
foreign import _ajax
305-
:: forall e. Fn5 (String -> String -> ResponseHeader)
306-
AjaxRequest
307-
(XMLHttpRequest -> Canceler (ajax :: AJAX | e))
308-
(Error -> Eff (ajax :: AJAX | e) Unit)
309-
(AffjaxResponse Foreign -> Eff (ajax :: AJAX | e) Unit)
310-
(Eff (ajax :: AJAX | e) (Canceler (ajax :: AJAX | e)))
311-
312-
cancelAjax :: forall e. XMLHttpRequest -> Canceler (ajax :: AJAX | e)
313-
cancelAjax xhr = Canceler \err -> makeAff (\eb cb -> runFn4 _cancelAjax xhr err eb cb)
314-
315-
foreign import _cancelAjax
316-
:: forall e. Fn4 XMLHttpRequest
317-
Error
318-
(Error -> Eff (ajax :: AJAX | e) Unit)
319-
(Boolean -> Eff (ajax :: AJAX | e) Unit)
320-
(Eff (ajax :: AJAX | e) Unit)
287+
foreign import _ajax :: forall e. Fn2 (String -> String -> ResponseHeader) AjaxRequest (AC.EffFnAff (ajax :: AJAX | e) (AffjaxResponse Foreign))

test/Main.purs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@ module Test.Main where
33
import Prelude
44
import Control.Monad.Aff.Console as A
55
import Network.HTTP.Affjax as AX
6-
import Control.Monad.Aff (Aff, cancel, forkAff, attempt, runAff, makeAff)
6+
import Control.Monad.Aff (Aff, forkAff, attempt, runAff, killFiber)
77
import Control.Monad.Aff.AVar (AVAR)
88
import Control.Monad.Eff (Eff)
99
import Control.Monad.Eff.Class (liftEff)
1010
import Control.Monad.Eff.Console (CONSOLE, log, logShow)
1111
import Control.Monad.Eff.Exception (EXCEPTION, error, throwException)
1212
import Control.Monad.Eff.Ref (REF)
13-
import Data.Either (Either(..))
13+
import Control.Monad.Error.Class (throwError)
14+
import Data.Either (Either(..), either)
1415
import Data.Foreign (Foreign, unsafeFromForeign)
1516
import Data.Maybe (Maybe(..))
1617
import Data.Time.Duration (Milliseconds(..))
@@ -24,7 +25,7 @@ logAny' = liftEff <<< logAny
2425
type Assert e a = Aff (exception :: EXCEPTION, console :: CONSOLE, ajax :: AX.AJAX | e) a
2526

2627
assertFail :: forall e a. String -> Assert e a
27-
assertFail msg = makeAff \errback _ -> errback (error msg)
28+
assertFail = throwError <<< error
2829

2930
assertMsg :: forall e. String -> Boolean -> Assert e Unit
3031
assertMsg _ true = pure unit
@@ -57,7 +58,7 @@ type MainEffects e =
5758
)
5859

5960
main :: Eff (MainEffects (ajax :: AX.AJAX)) Unit
60-
main = void $ runAff (\e -> logShow e >>= \_ -> throwException e) (const $ log "affjax: All good!") $ do
61+
main = void $ runAff (either (\e -> logShow e *> throwException e) (const $ log "affjax: All good!")) do
6162
let ok200 = StatusCode 200
6263
let notFound404 = StatusCode 404
6364

@@ -112,6 +113,5 @@ main = void $ runAff (\e -> logShow e >>= \_ -> throwException e) (const $ log "
112113
-- assertEq (Just "test=test") (lookupHeader "Set-Cookie" res.headers)
113114

114115
A.log "Testing cancellation"
115-
canceler <- forkAff (AX.post_ mirror "do it now")
116-
canceled <- canceler `cancel` error "Pull the cord!"
117-
assertMsg "Should have been canceled" canceled
116+
forkAff (AX.post_ mirror "do it now") >>= killFiber (error "Pull the cord!")
117+
assertMsg "Should have been canceled" true

0 commit comments

Comments
 (0)