Return ajax response via JS Module pattern - javascript

UPDATE:
I decided that using the JS Module Pattern was not "keeping it simple", so I scrapped it and used jQuery's deferred object to return the data I was looking for. What I really needed was to simply load a JSON file and populate an object. I was just trying to be too fancy by incorporating the JS Module Pattern.
Many thanks to #kiramishima for the correct answer.
Below is the finished code:
function getData(){
var url = CONTEXT + "/json/myJsonFile.json";
return $.getJSON(url);
}
getData()
.done(function(data){
myGlobalObj = data;
})
.fail(function(data){
console.log("fetching JSON file failed");
});
I think I'm getting a little too fancy for my own good here. I'm loading a JSON file and trying to return the API via JS module pattern. Problem is that I believe I'm not implementing the promise correctly and I don't know how to fix it.
Here's my JSON:
{
"result": {
"one": {
"first_key":"adda",
"second_key":"beeb",
"third_key":"cffc"
},
"two": {
"first_key":"adda",
"second_key":"beeb",
"third_key":"cffc"
}
}
}
And here's my JS Module implementation:
var data = (function() {
var url = "/json/dummy.json";
var getAllData = function() {
return $.getJSON(url, function(result){});
};
var promise = getAllData(); // the promise
return {
getFirstObjSecondKey:function() {
return promise.success(function(data) {
return data.result.one.second_key;
});
},
getSecondObjThirdKey:function() {
return promise.success(function(data) {
return data.result.two.third_key;
});
},
};
})();
The problem is that "getAllData()" is coming back as undefined and I'm not sure why; that method returns a Promise that I should be able to handle in the "done" function. How far off am I?
Thanks for any helpful input. This is the first time I'm messing with the JS Module Pattern.

I dont know what is your problem, but I test with:
var getAllData = function() {
return $.getJSON('/json/dummy.json', function(result){})
}
getAllData().done(function(data){ console.log(data.result.one.second_key) }) // prints beeb
works fine in that case, but if try this:
var data = (function() {
var url = '/json/dummy.json';
var getAllData = function() {
return $.getJSON(url, function(result){});
};
return {
getFirstObjSecondKey:function() {
getAllData().done(function(data) {
return data.login;
});
},
getSecondObjThirdKey:function() {
getAllData().done(function(data) {
return data.name;
});
},
};
})();
data.getFirstObjSecondKey returns undefined, then can u pass anonymous function:
var data = (function() {
var url = '/json/dummy.json';
var getAllData = function() {
return $.getJSON(url, function(result){});
};
return {
getFirstObjSecondKey:function(callback) {
getAllData().done(function(data) {
callback(data.result.one.second_key);
});
},
getSecondObjThirdKey:function(callback) {
getAllData().done(function(data) {
callback(data.result.two.third_key);
});
},
};
})();
var t;
data.getFirstObjSecondKey(function(data){
//data should contain the object fetched by getJSON
console.log(data); // prints beeb
t = data; // assign t
})
console.log(t) // prints beeb
Other solution, return always the deferred object

kiramishima's answer works, but it mixes callbacks with Promises. If you're using promises, you should try not to mix both styles.
You have to return a Promise from your functions. Remember that promises can be chained, that is, if you return a Promise from the done function, that becomes the new Promise
var data = (function() {
var url = "/json/dummy.json";
var getAllData = function() {
return $.getJSON(url, function(result){});
};
return {
getFirstObjSecondKey:function() {
return getAllData().done(function(data) {
return new Promise(function(resolve, reject){
resolve(data.result.one.second_key);
});
});
},
getSecondObjThirdKey:function() {
return getAllData().done(function(data) {
return new Promise(function(resolve, reject){
resolve(data.result.one.third_key);
});
});
},
};
})();
data.getFirstObjSecondKey().done(function(secondKey) {
console.log('Second key', secondKey);
});

Related

Angularjs Factory deferred's data disapearing

I'm trying to do a caching factory for http requests, so it doesn't make the server do a lot of work for the same request. But It seems my way of using deferred "swallows" the data, and I don't know why.
Console output for below:
data fetched:
Object {state: "OK", data: Object, errorMessage: null, exception: null}
success
undefined
ImportFactory:
factory("importFactory", function ($http, $q, loggingService) {
return{
fetchedData: [],
cacheTransport: function (transportsId, data) {
this.fetchedData.push({"transportsId": transportsId, "data": data});
},
getImport: function (transportsId) {
var factory = this;
var deferred = $q.defer();
var preFetchedTransport = this.findTransport(transportsId);
if (preFetchedTransport === null) {
console.log('fetching from backend');
return $http.post("/import/create/" + transportsId).then(function (data) {
console.log('data fetched:');
console.log(data);
factory.cacheTransport(transportsId, data);
deferred.resolve(data);
});
}
preFetchedTransport = deferred.promise;
return preFetchedTransport;
},
findTransport: function (transportsId) {
for (var i = 0; i < this.fetchedData.length; i++) {
var transportObj = this.fetchedData[i];
if (transportObj.transportsId === transportsId) {
return transportObj.data;
}
}
return null;
}
};
});
Controller
.controller('ImportController', function ($scope, $routeParams, importFactory){
$scope.transportId = $routeParams.id;
importFactory.getImport($scope.transportId).then(function (successData) {
console.log('success');
console.log(successData);
}, function (errorData) {
console.log('error');
console.log(errorData);
});
You basically need this: Demo here.
var cachedPromises = {};
return {
getStuff: function(id) {
if (!cachedPromises[id]) {
cachedPromises[id] = $http.post("/import/create/" + id).then(function(resp) {
return resp.data;
});
}
return cachedPromises[id];
}
};
Now, when you fetch that data, you can manipulate and it will be changed when you access it in the future.
myService.getStuff(whatever).then(function(data) {
data.foo = 'abc';
});
//elsewhere
myService.getStuff(whatever).then(function(data) {
console.log(data.foo); // 'abc'
});
Here's a demo that does this, as well as a view updating trick (bind the object to the view before the data comes in), and an idea of how you could change the data separately from the cache, in case you want to have the original data and the changing data. http://jsbin.com/notawo/2/edit
Remember to avoid that nasty promise anti-pattern. If you already have a promise, use that instead of creating another with $q. $http already returns a promise and that promise is sufficient for whatever you need if you use it properly.
just change the loop condition look like this and then test i think your function and defer is work fine but the loop does not sent the correct data
for(var i = 0; i < this.fetchedData.length; i++) {
if (this.fetchedData[i].transportsId === transportsId) {
return this.fetchedData[i].data;
}
}
return null;
}
The reason you are getting undefined is you are not returning anything from the $http.post().then() !
Also in your getImport() function you are returning an empty promise when the transport is already cached. You need to resolve it to your already cached transport object.
getImport: function (transportsId) {
var factory = this;
var deferred = $q.defer();
var preFetchedTransport = this.findTransport(transportsId);
if (preFetchedTransport === null) {
console.log('fetching from backend');
return $http.post("/import/create/" + transportsId).then(function (data) {
console.log('data fetched:');
console.log(data);
factory.cacheTransport(transportsId, data);
return data; //this was missing
});
}
// resolve it with transport object if cached
deferred.resolve(preFetchedTransport);
return deferred.promise;
},

Multiple Promise Chains in Single Function

I have some code that will dynamically generate an AJAX request based off a scenario that I'm retrieving via an AJAX request to a server.
The idea is that:
A server provides a "Scenario" for me to generate an AJAX Request.
I generate an AJAX Request based off the Scenario.
I then repeat this process, over and over in a Loop.
I'm doing this with promises here: http://jsfiddle.net/3Lddzp9j/11/
However, I'm trying to edit the code above so I can handle an array of scenarios from the initial AJAX request.
IE:
{
"base": {
"frequency": "5000"
},
"endpoints": [
{
"method": "GET",
"type": "JSON",
"endPoint": "https://api.github.com/users/alvarengarichard",
"queryParams": {
"objectives": "objective1, objective2, objective3"
}
},
{
"method": "GET",
"type": "JSON",
"endPoint": "https://api.github.com/users/dkang",
"queryParams": {
"objectives": "objective1, objective2, objective3"
}
}
]
This seems like it would be straight forward, but the issue seems to be in the "waitForTimeout" function.
I'm unable to figure out how to run multiple promise chains. I have an array of promises in the "deferred" variable, but the chain only continues on the first one--despite being in a for loop.
Could anyone provide insight as to why this is? You can see where this is occuring here: http://jsfiddle.net/3Lddzp9j/10/
The main problems are that :
waitForTimeout isn't passing on all the instructions
even if waitForTimeout was fixed, then callApi isn't written to perform multiple ajax calls.
There's a number of other issues with the code.
you really need some data checking (and associated error handling) to ensure that expected components exist in the data.
mapToInstruction is an unnecessary step - you can map straight from data to ajax options - no need for an intermediate data transform.
waitForTimeout can be greatly simplified to a single promise, resolved by a single timeout.
synchronous functions in a promise chain don't need to return a promise - they can return a result or undefined.
Sticking with jQuery all through, you should end up with something like this :
var App = (function ($) {
// Gets the scenario from the API
// sugar for $.ajax with GET as method - NOTE: this returns a promise
var getScenario = function () {
console.log('Getting scenario ...');
return $.get('http://demo3858327.mockable.io/scenario2');
};
var checkData = function (data) {
if(!data.endpoints || !data.endpoints.length) {
return $.Deferred().reject('no endpoints').promise();
}
data.base = data.base || {};
data.base.frequency = data.base.frequency || 1000;//default value
};
var waitForTimeout = function(data) {
return $.Deferred(function(dfrd) {
setTimeout(function() {
dfrd.resolve(data.endpoints);
}, data.base.frequency);
}).promise();
};
var callApi = function(endpoints) {
console.log('Calling API with given instructions ...');
return $.when.apply(null, endpoints.map(ep) {
return $.ajax({
type: ep.method,
dataType: ep.type,
url: ep.endpoint
}).then(null, function(jqXHR, textStatus, errorThrown) {
return textStatus;
});
}).then(function() {
//convert arguments to an array of results
return $.map(arguments, function(arg) {
return arg[0];
});
});
};
var handleResults = function(results) {
// results is an array of data values/objects returned by the ajax calls.
console.log("Handling data ...");
...
};
// The 'run' method
var run = function() {
getScenario()
.then(checkData)
.then(waitForTimeout)
.then(callApi)
.then(handleResults)
.then(null, function(reason) {
console.error(reason);
})
.then(run);
};
return {
run : run
}
})(jQuery);
App.run();
This will stop on error but could be easily adapted to continue.
I'll try to answer your question using KrisKowal's q since I'm not very proficient with the promises generated by jQuery.
First of all I'm not sure whether you want to solve the array of promises in series or in parallel, in the solution proposed I resolved all of them in parallel :), to solve them in series I'd use Q's reduce
function getScenario() { ... }
function ajaxRequest(instruction) { ... }
function createPromisifiedInstruction(instruction) {
// delay with frequency, not sure why you want to do this :(
return Q.delay(instruction.frequency)
.then(function () {
return this.ajaxRequest(instruction);
});
}
function run() {
getScenario()
.then(function (data) {
var promises = [];
var instruction;
var i;
for (i = 0; i < data.endpoints.length; i += 1) {
instruction = {
method: data.endpoints[i].method,
type: data.endpoints[i].type,
endpoint: data.endpoints[i].endPoint,
frequency: data.base.frequency
};
promises.push(createPromisifiedInstruction(instruction));
}
// alternative Q.allSettled if all the promises don't need to
// be fulfilled (some of them might be rejected)
return Q.all(promises);
})
.then(function (instructionsResults) {
// instructions results is an array with the result of each
// promisified instruction
})
.then(run)
.done();
}
run();
Ok let me explain the solution above:
first of all assume that getScenario gets you the initial json you start with (actually returns a promise which is resolved with the json)
create the structure of each instruction
promisify each instruction, so that each one is actually a promise whose
resolution value will be the promise returned by ajaxRequest
ajaxRequest returns a promise whose resolution value is the result of the request, which also means that createPromisifiedInstruction resolution value will be the resolution value of ajaxRequest
Return a single promise with Q.all, what it actually does is fulfill itself when all the promises it was built with are resolved :), if one of them fails and you actually need to resolve the promise anyways use Q.allSettled
Do whatever you want with the resolution value of all the previous promises, note that instructionResults is an array holding the resolution value of each promise in the order they were declared
Reference: KrisKowal's Q
Try utilizing deferred.notify within setTimeout and Number(settings.frequency) * (1 + key) as setTimeout duration; msg at deferred.notify logged to console at deferred.progress callback , third function argument within .then following timeout
var App = (function ($) {
var getScenario = function () {
console.log("Getting scenario ...");
return $.get("http://demo3858327.mockable.io/scenario2");
};
var mapToInstruction = function (data) {
var res = $.map(data.endpoints, function(settings, key) {
return {
method:settings.method,
type:settings.type,
endpoint:settings.endPoint,
frequency:data.base.frequency
}
});
console.log("Instructions recieved:", res);
return res
};
var waitForTimeout = function(instruction) {
var res = $.when.apply(instruction,
$.map(instruction, function(settings, key) {
return new $.Deferred(function(dfd) {
setTimeout(function() {
dfd.notify("Waiting for "
+ settings.frequency
+ " ms")
.resolve(settings);
}, Number(settings.frequency) * (1 + key));
}).promise()
})
)
.then(function() {
return this
}, function(err) {
console.log("error", err)
}
, function(msg) {
console.log("\r\n" + msg + "\r\nat " + $.now() + "\r\n")
});
return res
};
var callApi = function(instruction) {
console.log("Calling API with given instructions ..."
, instruction);
var res = $.when.apply(instruction,
$.map(instruction, function(request, key) {
return request.then(function(settings) {
return $.ajax({
type: settings.method,
dataType: settings.type,
url: settings.endpoint
});
})
})
)
.then(function(data) {
return $.map(arguments, function(response, key) {
return response[0]
})
})
return res
};
var handleResults = function(data) {
console.log("Handling data ..."
, JSON.stringify(data, null, 4));
return data
};
var run = function() {
getScenario()
.then(mapToInstruction)
.then(waitForTimeout)
.then(callApi)
.then(handleResults)
.then(run);
};
return {
// This will expose only the run method
// but will keep all other functions private
run : run
}
})($);
// ... And start the app
App.run();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
jsfiddle http://jsfiddle.net/3Lddzp9j/13/
You have a return statement in the loop in your waitForTimeout function. This means that the function is going to return after the first iteration of the loop, and that is where you are going wrong.
You're also using the deferred antipattern and are using promises in places where you don't need them. You don't need to return a promise from a then handler unless there's something to await.
The key is that you need to map each of your instructions to a promise. Array#map is perfect for this. And please use a proper promise library, not jQuery promises (edit but if you absolutely must use jQuery promises...):
var App = (function ($) {
// Gets the scenario from the API
// NOTE: this returns a promise
var getScenario = function () {
console.log('Getting scenario ...');
return $.get('http://demo3858327.mockable.io/scenario');
};
// mapToInstructions is basically unnecessary. each instruction does
// not need its own timeout if they're all the same value, and you're not
// reshaping the original values in any significant way
// This wraps the setTimeout into a promise, again
// so we can chain it
var waitForTimeout = function(data) {
var d = $.Deferred();
setTimeout(function () {
d.resolve(data.endpoints);
}, data.base.frequency);
return d.promise();
};
var callApi = function(instruction) {
return $.ajax({
type: instruction.method,
dataType: instruction.type,
url: instruction.endPoint
});
};
// Final step: call the API from the
// provided instructions
var callApis = function(instructions) {
console.log(instructions);
console.log('Calling API with given instructions ...');
return $.when.apply($, instructions.map(callApi));
};
var handleResults = function() {
var data = Array.prototype.slice(arguments);
console.log("Handling data ...");
};
// The 'run' method
var run = function() {
getScenario()
.then(waitForTimeout)
.then(callApis)
.then(handleResults)
.then(run);
};
return {
run : run
}
})($);
App.run();

Angular promises: get data from buffer if available

In this scenario the requirement is to get the data with an Http request if the data is not in a buffer. If it's in the buffer, use it from there without the Http request.
I tried the code below but it doesn't make much sense; if the data is in the buffer I don't know if I should return from the function doing nothing or return the deferred promise. Any thoughts?
var dataBuffer = null;
var getData = function() {
var deferred = $q.defer();
if (dataBuffer != null) { // this is the part I'm not convinced
deferred.resolve();
return;
}
$http.get('/some/url/')
.success(function(data) {
dataBuffer = data;
deferred.resolve();
})
.error(function(data) {
deferred.reject();
});
return deferred.promise;
};
Invoked in the following way:
var promise = getData();
promise.then (
function(response) {
dataBuffer = .... // dataBuffer contains data
}
);
There is a clean simple way to use promises when you're not sure which is the code you're executing is asynchronous or not and it's using $q.when
So the code can be:
var getData = function() {
return $q.when(dataBuffer ? dataBuffer: $http.get('/some/url'))
};
Then when calling getData you can use the same code you posted or just simply:
getData()
.then(function(response){//...
})
.catch(function(err){//..
});
Beware of the deferred antipattern. You can accomplish what you are trying to do very cleanly, like this:
var dataBuffer;
var getData = function() {
if (dataBuffer) {
// return a resolved promise for dataBuffer if it is already populated
return $q.when(dataBuffer);
}
$http.get('/some/url/')
.then(function (data) {
dataBuffer = data.data;
return dataBuffer;
});
};
getData().then(function (data) {
// data contains the data you want
})
.catch(function (error) {
// error occurred.
});
dataBuffer should not be accessed outside of your getData function. To make this perfectly clear, you can wrap them together in an IIFE, although this is optional:
var getData = (function () {
var dataBuffer;
return function() {
if (dataBuffer) {
// return a resolved promise for dataBuffer if it is already populated
return $q.when(dataBuffer);
}
$http.get('/some/url/')
.then(function (data) {
dataBuffer = data.data;
return dataBuffer;
});
};
})();
getData().then(..etc etc etc...);
As a final note, remember that you can use $http's built-in caching features, and not have to reinvent the wheel with your own buffers:
// much simpler, isn't it?
var getData = function() {
$http.get('/some/url/', { cache: true }) // enable caching
.then(function (data) { return data.data });
};
getData().then(...etc etc etc...);
Why dont you enable cache instead of handling the buffer manually.
$http.get('/some/url/',{ cache: true})
.success(function(data) {
deferred.resolve(data);
})
.error(function(data) {
deferred.reject();
});

Nodejs - SolrClient, how to wait for response

I got a question regarding the solr-client module of nodejs. I'm using this module for querying against a solr-index.
The module itself works fine as long as I don't have to wait for finishing of the query and as long I need the result only as a async result.
But currently I cannot find out, how I will be able to await the finishing of a search request and use the result in a sequential way.
I have the follwing method in my manager
SolrManager.prototype.promisedQuery = function(query, callback) {
var solrClient = solr.createClient(this.configuration.cores.page);
var docs = null;
var finished = false;
var deferred = Q.defer();
var request = solrClient.search(query, function(err,obj){
if (!err) {
if (obj.response.numFound > 0) {
deferred.resolve(obj.response.docs);
} else {
deferred.resolve(null);
}
} else {
deferred.reject(err);
}
});
var records = null;
var promise = deferred.promise;
promise.then(function(result) {
records = result;
}).fail(function(error){
records = error;
});
return records;
};
The problem here is, that I try to wait for the result of the query and use it as return value of "promisedQuery".
I try since days to use this method in a sequential call, also with different additional modules like "wait.for", "q", etc. but nothing seems to work.
The callback function of the solr-client will always be executed after the manager-method has already returned. Also the promise-methods will be even called after the return from the manager-method.
Can someone help me out on that topic or have some tips, how I can await the response of the solr-client-search operation and then give it back in a sequential way?
Thanks for any help.
Udo Gerhards
over one week, it seems now that I have found a solution:
SolrManager.prototype.promisedQuery = function(query, callback) {
var solrClient = solr.createClient(this.configuration.cores.page);
var docs = null;
var deferred = Q.defer();
var request = solrClient.search(query, function(err,obj){
if (!err) {
if (obj.response.numFound > 0) {
deferred.resolve(obj.response.docs);
} else {
deferred.resolve(null);
}
} else {
deferred.reject(err);
}
});
return deferred.promise;
};
in all other managers, which are calling the above function:
...
var dbPromise = this.solrManager.promisedQuery(query);
var _self = this;
return Q.async(function*(){
var result = yield dbPromise;
return result;
});
...
After first tests, it seems that synchronized methods will wait until the promise is settled.
The only thing is, that it runs only with NodeJs version 0.11.10, which supports generator functions, with activated --harmony-flag and "q"-module.
Best regards
Udo
You are just using the promises a bit incorrectly. Instead of returning records, you need to return 'deferred.promise'. It should look something like this (note that you don't need the callback you passed into promisedQuery).
SolrManager.prototype.promisedQuery = function(query) {
var solrClient = solr.createClient(this.configuration.cores.page),
deferred = Q.defer();
solrClient.search(query, function(err,obj){
if (!err) {
if (obj.response.numFound > 0) {
deferred.resolve(obj.response.docs);
} else {
deferred.resolve(null);
}
} else {
deferred.reject(err);
}
});
return deferred.promise;
};
To use it you would do something like:
SolrManager.promisedQuery(myquery)
.then(function (data) {
// data is whatever your 'resolved' in promisedQuery
}, function (err) {
// err is whatever you rejected in promisedQuery
});
based on rquinns answer I've changed the code like follows:
SolrManager.prototype.promisedQuery = function(query, callback) {
var solrClient = solr.createClient(this.configuration.cores.page);
var docs = null;
var finished = false;
var deferred = Q.defer();
var request = solrClient.search(query, function(err,obj){
if (!err) {
if (obj.response.numFound > 0) {
deferred.resolve(obj.response.docs);
} else {
deferred.resolve(null);
}
} else {
deferred.reject(err);
}
});
return deferred.promise;
};
...
DemoObject.prototype.toString = function() {
return SolrManager.promisedQuery(this.query).then(function(result){
return result['title'];
}).fail(function(error){
return error;
});
};
DemoObject.prototype.typeOf = function() {
return SolrManager.promisedQuery(this.query).then(function(result){
return result['title'];
}).fail(function(error){
return error;
});
};
I think, this is the right way to use the "promise"-object. But what happens when i do the follwing:
...
var demoObject = new DemoObject();
demoObject.query = "id:1";
console.log(''+demoObject);
...
or if I use "demoObject" by concatenating it to a string
...
var string = "Some string "+demoObject;
...
In case of the string concatenation, I'm currently not sure that the string will contain also the title field from the database. Same for console output.
Will nodejs be so intelligent that it resolves for e.g. the string concatenation "after" the results from the database will be available?
BR
Udo

Unable to get property 'then' using promises

I want to have the most clear code into my app. So I decided to separate the xhr call and the parsing from the view.js.
To do so I added :
In View.js
this._pagePromises.push(myapp.Services.Foo.getFoo()
.then(
function success(results) {
var x = results;
},
function error() {
// TODO - handle the error.
}
));
And in Services.js
Foo:
{
getFoo: function () {
WinJS.xhr({ url: "http://sampleurl.com" }).done(
function completed(request) {
//parse request
var obj = myapp.Parser.parse(request);
return obj;
},
function error(request) {
// handle error conditions.
}
);
}
}
But I have this exception :
0x800a138f - JavaScript runtime error: Unable to get property 'then'
of undefined or null reference
What I want there is :
Start the promise in view.js do some stuff and update the view when getFoo() is completed. I'm not doing this the right way but as a C# developper I have some difficulties to understand this pattern.
Edit :
There is my updated code:
getFoo: function () {
var promise = WinJS.xhr({ url: myapp.WebServices.getfooUrl() });
promise.done(
function completed(request) {
var xmlElements = request.responseXML;
var parser = new myapp.Parser.foo();
var items = parser.parse(xmlElements);
return items;
},
function error(request) {
// handle error conditions.
}
);
return promise;
}
It solved my issue about the 'then' but "return promise" is called before the "return items". So my "caller" does only get the promise and not his result.
What did I miss ?
Edit 2 :
There is the correct way to do this :
Foo:
{
getFooAsync: function () {
return WinJS.Promise.wrap(this.getXmlFooAsync().then(
function completed(request) {
var xmlElements = request.responseXML;
var parser = new myapp.Parser.Foo();
var items = parser.parse(xmlElements);
return items;
}
));
},
getXmlFooAsync: function () {
return WinJS.xhr({ url: "http://sampleurl.com" });
}
}
A more compact way of doing this is to have your function return the return value from WinJS.xhr().then(). What this does is return a promise that will be fulfilled with the return value of your inner completed handler:
Foo:
{
getFooAsync: function () {
return WinJS.xhr({ url: "http://sampleurl.com" }).then(
function completed(request) {
var xmlElements = request.responseXML;
var parser = new myapp.Parser.Foo();
var items = parser.parse(xmlElements);
return items;
}
));
},
}
The caller can then use then/done on the promise it gets from getFooAsync, and the result in the completed handler will be items as returned by the completed handler. (You would not use .done inside this function because you're wanting to return a promise.)
This is the specified behavior of then in Promises-A, to allow for chaining. For more on this, see my post on the Windows 8 Developer Blog, http://blogs.msdn.com/b/windowsappdev/archive/2013/06/11/all-about-promises-for-windows-store-apps-written-in-javascript.aspx.

Categories

Resources