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

Last change on this file since 525 was 525, checked in by hendrikvanantwerpen, 11 years ago
  • Allow empty subcodes.
  • Use HTTPResult exclusively on server (no more q).
  • Set readonly & disabled on ourselves as well in _ComplexValueMixin
  • Split server into several modules.
  • Check codes on the variable level, not question level.
  • We can add modules in design documents now.
File size: 3.3 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    var ret = handler.f(this.status,this.result);
42    if ( ret instanceof HTTPResult ) {
43        ret.handle(handler.next.set.bind(handler.next));
44    } else {
45        handler.next.set(this.status,ret);
46    }
47};
48
49/* handle :: Either Callback
50 *                  {status:Number*: (result -> Either HTTPResult Any),
51 *                   'default'?: Callback}
52 *           -> HTTPResult
53 */
54HTTPResult.prototype.handle = function(fOrObj) {
55    var f = _.isFunction(fOrObj) ?
56            fOrObj :
57            function(status,result) {
58                if ( status in fOrObj ) {
59                    return fOrObj[status](result);
60                } else if ( 'default' in fOrObj ) {
61                    return fOrObj['default'](status,result);
62                } else {
63                    return result;
64                }
65            };
66    var next = new HTTPResult();
67    var handler = {
68        f: f,
69        next: next
70    };
71    if ( this.isSet() ) {
72        this._fire(handler);
73    } else {
74        this._handlers.push(handler);
75    }
76    return next;
77};
78
79// then :: onSuccess:(result:Any -> status:Number)? ->
80//         onError:(result:Any -> status:Number)? -> HTTPResult
81HTTPResult.prototype.then = function(onSuccess,onError) {
82    var f = function(status,result) {
83        if ( status >= 200 && status < 300 && onSuccess ) {
84            if ( onSuccess ) {
85                result = onSuccess(result,status);
86            }
87        } else {
88            if ( onError ) {
89                result = onError(result,status);
90            }
91        }
92        return result;
93    };
94    return this.handle(f);
95};
96
97HTTPResult.prototype.asCallback = function(status) {
98    status = status || 200;
99    return function(ex,result) {
100        if ( ex ) {
101            this.set(-1,ex);
102        } else {
103            this.set(status,result);
104        }
105    }.bind(this);
106};
107
108// when :: Either HTTPResult Any -> HTTPResult
109when = HTTPResult.when = function(status,valueOrResult) {
110    status = status || 200;
111    if ( valueOrResult instanceof HTTPResult ) {
112        return valueOrResult;
113    } else {
114        return new HTTPResult(status,valueOrResult);
115    }
116};
117
118// ok :: result:Any? -> HTTPResult
119HTTPResult.ok = function(result) {
120    return new HTTPResult(200,result);
121};
122
123// fail :: error:Any? -> HTTPResult
124HTTPResult.fail = function(error) {
125    return new HTTPResult(-1,error);
126};
127
128module.exports = HTTPResult;
Note: See TracBrowser for help on using the repository browser.