Ignore:
Timestamp:
03/19/14 21:33:13 (11 years ago)
Author:
hendrikvanantwerpen
Message:
  • 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:
1 edited

Legend:

Unmodified
Added
Removed
  • Dev/trunk/src/server/util/http-result.js

    r487 r525  
    1 // <init> :: status? -> result? -> HTTPResult
     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;
    211function HTTPResult(status,result) {
     12    this.id = counter++;
    313    this.status = 0;
    414    this.result = null;
     
    919}
    1020
    11 HTTPResult.fromResponsePromise = function(promise,errorHandler) {
    12     var result = new HTTPResult();
    13     promise.then(function(response){
    14         result.set(response.statusCode,response.body);
    15     }, errorHandler && function(error){
    16         var ret = errorHandler(error);
    17         if ( ret.constructor === HTTPResult ) {
    18             ret.handle(result.set.bind(result));
    19         } else {
    20             result.set(500,ret);
    21         }
    22     });
    23     return result;
    24 };
    25 
    2621// isSet :: Bool
    2722HTTPResult.prototype.isSet = function() {
     
    2924};
    3025
    31 // set :: status -> result? -> ()
     26// set :: status:Number -> result:Any? -> ()
    3227HTTPResult.prototype.set = function(status,result) {
    33     if ( this.isSet() ) { throw new Error("Result was already set."); }
    34     if ( typeof status !== 'number' ) { throw new Error("Status must be a number."); }
     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    }
    3534    this.status = status;
    3635    this.result = result;
    37     for ( var i = 0; i < this._handlers.length; i++ ) {
    38         this._fire(this._handlers[i]);
     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);
    3946    }
    4047};
    4148
    42 // _fire :: (status -> result -> Either HTTPResult Any) -> ()
    43 HTTPResult.prototype._fire = function(f) {
    44     var ret = f(this.status,this.result);
    45     if ( ret.constructor === HTTPResult ) {
    46         ret.handle(f._next.set.bind(f._next));
    47     } else {
    48         f._next.set(this.status,ret);
    49     }
    50 };
    51 
    52 /* handle :: Either (status -> result -> Either HTTPResult Any)
    53  *                  {number: (result -> Either HTTPResult Any),
    54  *                   'default': (status -> result -> Either HTTPResult Any)}
     49/* handle :: Either Callback
     50 *                  {status:Number*: (result -> Either HTTPResult Any),
     51 *                   'default'?: Callback}
    5552 *           -> HTTPResult
    5653 */
    5754HTTPResult.prototype.handle = function(fOrObj) {
    58     var f = typeof fOrObj === 'function' ?
     55    var f = _.isFunction(fOrObj) ?
    5956            fOrObj :
    6057            function(status,result) {
     
    6764                }
    6865            };
    69     f._next = new HTTPResult();
     66    var next = new HTTPResult();
     67    var handler = {
     68        f: f,
     69        next: next
     70    };
    7071    if ( this.isSet() ) {
    71         this._fire(f);
     72        this._fire(handler);
    7273    } else {
    73         this._handlers.push(f);
     74        this._handlers.push(handler);
    7475    }
    75     return f._next;
     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);
    76126};
    77127
Note: See TracChangeset for help on using the changeset viewer.