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:
- this student course form.
- for each row, users type person number , on column they'll type list of course ids separated commas. eg 100, 200, 300.
- the purpose of computed observable store array containing course details courses entered in step 2.
- the details obtained firing ajax calls each course , storing http response in array.
- 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:
- make simple observable hold result
- make dictionary of promises you'll keep in sync array of course ids
- when array of course ids change, add / remove dictionary of promises
- 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
Post a Comment