source: Dev/trunk/src/server/util/http-result.js @ 531

Last change on this file since 531 was 531, checked in by hendrikvanantwerpen, 11 years ago
  • Return to using truly ISO formatted dates, including milliseconds.
  • Also set constraint on surveyrun dates when value is initially set.
  • Separate runs & results from surveys and questions.
  • Moved date & email format to schema itself.
File size: 3.8 KB
Line 
1var _ = require('underscore')
2  ;
3
4var when;
5
6// type Callback = status:Number -> result:Any -> Either HTTPResult Any
7// type Handler = { f:Callback, next:HTTPResult }
8
9// <init> :: status:Number? -> result:Any? -> HTTPResult
10var counter = 0;
11function HTTPResult(status,result) {
12    this.id = counter++;
13    this.status = 0;
14    this.result = null;
15    this._handlers = [];
16    if ( status ) {
17        this.set(status,result);
18    }
19}
20
21// isSet :: Bool
22HTTPResult.prototype.isSet = function() {
23    return this.status !== 0;
24};
25
26// set :: status:Number -> result:Any? -> ()
27HTTPResult.prototype.set = function(status,result) {
28    if ( this.isSet() ) {
29        throw new Error("Result was already set.");
30    }
31    if ( !_.isNumber(status) ) {
32        throw new Error("Status must be a number.");
33    }
34    this.status = status;
35    this.result = result;
36    _.each(this._handlers,this._fire.bind(this));
37};
38
39// _fire :: Handler -> ()
40HTTPResult.prototype._fire = function(handler) {
41    try {
42        var ret = handler.f(this.status,this.result);
43        if ( ret instanceof HTTPResult ) {
44            ret.handle(handler.next.set.bind(handler.next));
45        } else {
46            handler.next.set(this.status,ret);
47        }
48    } catch(ex) {
49        console.log('HTTPResult','exception',ex.toString(),ex.stack);
50        handler.next.set(-1,ex);
51    }
52};
53
54/* handle :: Either Callback
55 *                  {status:Number*: (result -> Either HTTPResult Any),
56 *                   'default'?: Callback}
57 *           -> HTTPResult
58 */
59HTTPResult.prototype.handle = function(fOrObj) {
60    var f = _.isFunction(fOrObj) ?
61            fOrObj :
62            function(status,result) {
63                if ( status in fOrObj ) {
64                    return fOrObj[status](result);
65                } else if ( status >= 200 && status < 300 &&
66                            'success' in fOrObj ) {
67                    return fOrObj.success(status,result);
68                } else if ( !(status >= 200 && status < 300) &&
69                            'failure' in fOrObj ) {
70                    return fOrObj.failure(status,result);
71                } else if ( 'default' in fOrObj ) {
72                    return fOrObj['default'](status,result);
73                } else {
74                    return result;
75                }
76            };
77    var next = new HTTPResult();
78    var handler = {
79        f: f,
80        next: next
81    };
82    if ( this.isSet() ) {
83        this._fire(handler);
84    } else {
85        this._handlers.push(handler);
86    }
87    return next;
88};
89
90// then :: onSuccess:(result:Any -> status:Number)? ->
91//         onError:(result:Any -> status:Number)? -> HTTPResult
92HTTPResult.prototype.then = function(onSuccess,onError) {
93    var f = function(status,result) {
94        if ( status >= 200 && status < 300 && onSuccess ) {
95            if ( onSuccess ) {
96                result = onSuccess(result,status);
97            }
98        } else {
99            if ( onError ) {
100                result = onError(result,status);
101            }
102        }
103        return result;
104    };
105    return this.handle(f);
106};
107
108HTTPResult.prototype.asCallback = function(status) {
109    status = status || 200;
110    return function(ex,result) {
111        if ( ex ) {
112            this.set(-1,ex);
113        } else {
114            this.set(status,result);
115        }
116    }.bind(this);
117};
118
119// when :: Either HTTPResult Any -> HTTPResult
120when = HTTPResult.when = function(status,valueOrResult) {
121    status = status || 200;
122    if ( valueOrResult instanceof HTTPResult ) {
123        return valueOrResult;
124    } else {
125        return new HTTPResult(status,valueOrResult);
126    }
127};
128
129// ok :: result:Any? -> HTTPResult
130HTTPResult.ok = function(result) {
131    return new HTTPResult(200,result);
132};
133
134// fail :: error:Any? -> HTTPResult
135HTTPResult.fail = function(error) {
136    return new HTTPResult(-1,error);
137};
138
139module.exports = HTTPResult;
Note: See TracBrowser for help on using the repository browser.