javascript - How to implement asynchronous computed observable with multiple $.ajax calls? -


i'm attempting implement asynchronous computed observable show here.

i can 1 ajax call. challenge have @ moment how perform various ajax calls in loop building array asynchronously , returning array computed observable array using jquery promises.

basically html form works in following way:

  1. this student course form.
  2. for each row, users type person number , on column they'll type list of course ids separated commas. eg 100, 200, 300.
  3. the purpose of computed observable store array containing course details courses entered in step 2.
  4. the details obtained firing ajax calls each course , storing http response in array.
  5. i don't want users wait result, reason implement async computed observable.

my problem: i'm having problem returning value of final array observable. it's undefined. ajax calls work fine perhaps i'm still not handling promises correctly.

here's code class:

function asynccomputed(evaluator, owner) {             var result = ko.observable(), currentdeferred;             result.inprogress = ko.observable(false); // track whether we're waiting result              ko.computed(function () {                 // abort in-flight evaluation ensure notify latest value                 if (currentdeferred) { currentdeferred.reject(); }                  var evaluatorresult = evaluator.call(owner);                 // cope both asynchronous , synchronous values                 if (evaluatorresult && (typeof evaluatorresult.done == "function")) { // async                     result.inprogress(true);                     currentdeferred = $.deferred().done(function (data) {                         result.inprogress(false);                         result(data);                     });                     evaluatorresult.done(currentdeferred.resolve);                 } else // sync                     result(evaluatorresult);             });              return result;         }           function persondetails(id, personnumber, courseids) {             var self = this;             self.id = ko.observable(id);             self.personnumber = ko.observable(personnumber);             self.courseids = ko.observable(courseids);              // computed property extract pic details additional pics.             // computed observable returns response asynchronously             self.coursedetails = asynccomputed(function () {                 var courseidsarray = self.courseids().split(",");                 var arr = [];                 var arr_promises = [];                  function getcoursedetails(courseid) {                     var dfrd = $.deferred();                     var content = {};                      content.searchstring = courseid;                      var url = 'myurl';                      return $.ajax(url, {                         type: 'post',                         datatype: 'json',                         data: requestdata, // content of requestdata irrelevant. ajax call works fine.                         processdata: true,                         cache: false,                         async: true,                         contenttype: "application/json"                     }).done(function (data) {                         arr.push(new picdetails(data.genericidentifiersearchresult[0]));                     }).fail(function () {                         alert("could not retrieve pic details");                     }).then(function () {                         dfrd.resolve();                     });                  }                  if (courseidsarray.length > 0) {                      $.each(courseidsarray, function (index, courseid) {                         if (courseid.length > 0) {                             arr_promises.push(getcoursedetails(courseid));                         }                     });                 };                  $.when.apply($, arr_promises).done(function () {                     return arr;                 })              }, this);         }  

i have bit different approach, can build asynccomputed out of if prefer:

  1. make simple observable hold result
  2. make dictionary of promises you'll keep in sync array of course ids
  3. when array of course ids change, add / remove dictionary of promises
  4. wrap promises in when (like you're doing) , set result when they're done

basic idea:

var results = ko.observable([]); var loadingpromises = {}; var watcher = ko.computed(function () {      var ids = ko.unwrap(listofids);      if (ids && ids.length) {         ids.foreach(function (id) {             if (!loadingpromises.hasownproperty(id)) {                 loadingpromises[id] = $.get(url, {...id...});             }         });          var stillapplicablepromises = {};         var promises = []; // delete loadingpromises v8 optimizes delete poorly         object.getownpropertynames(loadingpromises).foreach(function (id) {             if (ids.indexof(id) >= 0) {                 stillapplicablepromises[id] = loadingpromises[id];                 promises.push(loadingpromises[id]);             }         });         loadingpromises = stillapplicablepromises;          $.when.apply(this, promises).then(function () {             // process arguments here like, they're responses promises             results(arguments);         });      } else {         loadingpromises = {};         results([]);     } }, this); 

this file (that may change) can see "in real life": https://github.com/wikimedia/analytics-dashiki/blob/master/src/components/wikimetrics-visualizer/wikimetrics-visualizer.js

and basic fiddle: http://jsfiddle.net/xtsekb20/1/


Comments

Popular posts from this blog

javascript - how to protect a flash video from refresh? -

android - Associate same looper with different threads -

visual studio 2010 - Connect to informix database windows form application -