Ignore:
Timestamp:
12/16/12 20:07:35 (12 years ago)
Author:
hendrikvanantwerpen
Message:

We can store answers for surveys now!

Introduces SurveyRun?, which can be edited. Workflow not quite clear yet. A
running survey can be accessed to leave a response. When the response
has an ID, it is loaded (used for closed surveys and continuations). A
researcher cannot create responses yet. He should also be able to add
comments to responses (that he creates).

Introduced caching of store requests.

Factored out path matching and formatting.

Put object creation in separate classes, to localize model/storage
dependency. Not consistent at the moment.

Location:
Dev/branches/rest-dojo-ui/client/qed/lib
Files:
1 added
1 moved

Legend:

Unmodified
Added
Removed
  • Dev/branches/rest-dojo-ui/client/qed/lib/async.js

    r415 r420  
    11define([
    2      'dojo/Deferred',
    3 ],function(Deferred){
     2     'dojo/_base/array',
     3     'dojo/_base/lang',
     4     'dojo/when',
     5     'dojo/Deferred'
     6],function(array,lang,when,Deferred){
    47
    5     function seq(functions) {
     8    /** Execute possible async functions in sequence
     9     * Execute functions in order. When a function returns a Promise,
     10     * the next function is only executed when the promise resolves.
     11     * If the function returns a value, the next function is executed
     12     * synchronously. The return value of every function is passed as argument
     13     * to the next.
     14     * Returns the return value of the last function in the chain.
     15     */
     16    function seq(functions,ctx) {
    617        var d = new Deferred();
    7         (function stepper(fs,arg) {
     18
     19        var cancelled = false;
     20        var running = null;
     21        function cancel(err) {
     22            if ( cancelled ) return;
     23            cancelled = true;
     24            running && running.cancel && !running.isFulfilled() && running.cancel();
     25            d.reject(err);
     26        }
     27
     28        function update(fs,arg) {
     29            if ( cancelled ) return;
    830            if ( fs.length > 0 ) {
    931                try {
    1032                    var f = fs.shift();
    11                     var ret = f(arg);
    12                     if ( ret && ret.then ) {
    13                         ret.then(function(ret){
    14                             stepper(fs,ret);
    15                         });
    16                     } else {
    17                         stepper(fs,ret);
    18                     }
     33                    running = when(f.call(ctx,arg))
     34                    .then(function(res){
     35                        update(fs,res);
     36                    },function(err){
     37                        cancel(err);
     38                    });
    1939                } catch(err) {
    20                     d.reject(err);
     40                    cancel(err);
    2141                }
    2242            } else {
    23                 d.resolve();
     43                d.resolve(arg);
    2444            }
    25         })(functions);
     45        }
     46
     47        update(functions);
     48
    2649        return d.promise;
    2750    }
    2851
     52    /** Execute possible async functions in parallel
     53     * Execute all functions in parallel, resolve only when all have resolved.
     54     * NB. When a function is not async, it will fully complete before the next
     55     * async function is started. If you mix async and non async functions, put
     56     * the sync functions last to fully exploit the async ones.
     57     * Return an array with all the return values of the functions.
     58     */
     59    function par(functions,ctx) {
     60        var d = new Deferred(cancel);
     61
     62        var cancelled = false;
     63        var running = [];
     64        function cancel(err) {
     65            if (cancelled) return;
     66            cancelled = true;
     67            array.forEach(running,function(running){
     68                running && running.cancel && !running.isFulfilled() && running.cancel();
     69            });
     70            d.reject(err);
     71        }
     72
     73        var results = [];
     74        var left = functions.length;
     75        function update(res,idx) {
     76            if (cancelled) return;
     77            results[idx] = res;
     78            left -= 1; // Works because/as long as AJAX/JS is single-threaded.
     79            if ( left === 0 ) {
     80                d.resolve(results);
     81            }
     82        }
     83
     84        array.forEach(functions,function(f,idx){
     85            if (cancelled) return;
     86            try {
     87                running.push(when(f.call(ctx)).then(function(res){
     88                    update(res,idx);
     89                },function(err){
     90                    cancel(err);
     91                }));
     92            } catch (err) {
     93                cancel();
     94            }
     95        });
     96
     97        return d.promise;
     98    }
     99
     100    /** Iterate over an array with async callback
     101     * Execute the callback and if it's async, wait until it's finished before
     102     * executing the next one.
     103     */
    29104    function forEach(list,callback,ctx) {
    30         var d = new Deferred();
    31         (function stepper(list,idx){
    32             if ( list.length > 0 ) {
    33                 var el = list.shift();
    34                 var ret = callback.call(ctx,el,idx);
    35                 if ( ret && ret.then ) {
    36                     ret.then(function(){
    37                         stepper(list,idx+1);
    38                     });
    39                 } else {
    40                     stepper(list,idx+1);
    41                 }
    42             } else {
    43                 d.resolve();
    44             }
    45         })(list,0);
    46         return d.promise;
     105        var fs = array.map(list,function(item,index,items){
     106            return lang.hitch(ctx,callback,item,index,items);
     107        });
     108        return seq(fs);
     109    }
     110
     111    /** Map a list, possible async
     112     * Map every element of a list, returning a promise to the mapped list.
     113     */
     114    function map(list,callback,ctx) {
     115        var fs = array.map(list,function(item,index,items){
     116            return lang.hitch(ctx,callback,item,index,items);
     117        });
     118        return par(fs);
    47119    }
    48120
    49121    return {
    50122        seq: seq,
    51         forEach: forEach
     123        par: par,
     124        forEach: forEach,
     125        map: map
    52126    };
    53127
Note: See TracChangeset for help on using the changeset viewer.