Return json object from dojo.xhrget - json

I am trying to get the json object from a dojo xhrGet call.
What I want is jsonobject = stuff;
I can see the json object in the console, but cannot access it!
var xhrargs = {
url: "/rest/url",
handleAs: "json",
preventCache : false,
load: function(json_results){
console.log(json_results);
store = json_results;
return dojo.toJson.json_results;
},
error: function(response, ioArgs) {
console.error(response);
console.error(response.stack);
}
};
var deferred = dojo.xhrGet(xhrargs);
console.log("Json is "+JSON.stringify(deferred));
The console.log part that shows the json_results is fine, exactly what I want.

The dojo.xhrXXX methods are asynchronous. This means that the lines following
var deferred = dojo.xhrGet(xhrargs);
Will continue to execute while the call to an external endpoint is processing. This means you need to use the promise API to tell a certain block of code to execute once the XHR request is complete:
var deferred = dojo.xhrGet(xhrargs);
deferred.then(function(result){
//this function executes when the deferred is resolved (complete)
console.log('result of xhr is ',result);
});
Due to the asynchronous nature of the request, for most intents and purposes that value doesn't exist outside the scope of the callback function. One way to structure your code around this is in multiple blocks. for example:
var xhrLoaded = function(results){
console.log('results = ',results);
store = results;
}
var performXhr = function(){
var xhrargs = {
url: "/rest/url",
handleAs: "json",
preventCache : false,
error: function(response, ioArgs) {
console.error(response);
console.error(response.stack);
}
};
var deferred = dojo.xhrGet(xhrargs);
deferred.then(xhrLoaded);
}
performXhr();
You can still access variables outside of the scope of the function (for example if store were defined globally).

try this
var xhrArgs = {
url:"MethodName.action?Id="+id,
handleAs: "json",
load: function(Data){
var values = Data;
var count = Object.keys(values).length // gives u all keys count in a json object. In mine it is 0,1,2,3
for (var i =0; i<count; i++){
var temp = values[i]; // values['name']
// do somthing ..
}
}
},
error: function(error){
alert(error);
}
}
dojo.xhrPost(xhrArgs);

Related

Pass a parameter from client-side to server side and get result

I knows it sounds basic but I can't seem to get it right. I'm trying to get a data from the API but it needs a parameter in order to obtain the data. How can I pass the parameter and get the result which is a JSON array
$(function() {
var proxy = 'http://192.168.1.126/lms-dev-noel/proxy.php';
var endpoint = 'account/';
var rt = 'GET';
var url = proxy+'?endpoint='+endpoint+'&rt='+rt;
var param = {
'lastsyncdate' : '2016-12-06'
};
$.get(url, function(param) {
console.log('Success');
});
});
ways to achieve this :
using jQuery.ajax() method :
var proxy = 'http://192.168.1.126/lms-dev-noel/proxy.php';
var endpoint = 'account/';
var url = proxy+'?endpoint='+endpoint+'&rt='+rt;
var method = 'GET';
var params = {
'lastsyncdate' : '2016-12-06'
};
$.ajax({
url: url,
type: method, //send it through get method
data: params,
success: function(response) {
//Do Something
},
error: function(xhr) {
//Do Something to handle error
}
});
using jQuery.get() method :
var proxy = 'http://192.168.1.126/lms-dev-noel/proxy.php';
var endpoint = 'account/';
var url = proxy+'?endpoint='+endpoint+'&rt='+rt;
var method = 'GET';
var params = {
'lastsyncdate' : '2016-12-06'
};
$.get(url, params, function(res) {
console.log(res);
});
I just pass parameters as name value pairs like so...
$.get(
"yoururl.php",
{ color: "red", size: "small" }, // your params go here as name / value pairs
function(response){
console.log(response);
}
);

Data not being fetched from json file

I am trying to fetch data from the static json file but the data is not getting displayed at all. What could be the possible reason for it.
Below is my code:
var Collection = Backbone.Collection.extend({
url: "names_of_people.json",
initialize: function() {
this.fetch();
}
});
collections = new Collection();
console.log("the length "+collections.length);
for (i=1;i<collections.length;i++)
{
console.log("done "+ collections.at(i).get("name"));
}
The problem is that this code:
console.log("the length "+collections.length);
for (i=1;i<collections.length;i++)
{
console.log("done "+ collections.at(i).get("name"));
}
ends up being executed before this.fetch() has completed. You'll need to either put your code in this.fetch's success callback, like this:
var Collection = Backbone.Collection.extend({
url: '/data.json',
initialize: function() {
this.fetch({
success: function() {
console.log(collections, 'the length ' + collections.length);
for (var i = 0; i < collections.length; i++) {
console.log('done ' + collections.at(i).get('name'));
}
}
});
}
});
var collections = new Collection();
or by listening to the collection's sync event, which occurs when this.fetch has completed successfully. This pattern is more commonly used in Backbone applications.
var Collection = Backbone.Collection.extend({
url: '/data.json',
initialize: function() {
this.listenTo(this, 'sync', this.syncExample);
this.fetch();
},
syncExample: function() {
console.log(collections, 'the length ' + collections.length);
for (var i = 0; i < collections.length; i++) {
console.log('done ' + collections.at(i).get('name'));
}
}
});
var collections = new Collection();
You can read more about Backbone's event system and the listenTo function here.
check backbone parse function. after fetch it will also call vlidate and parse if they exist.
EDIT: more detail
The key thing here I think is, the fetch() is asynchronous, so by the time you start loop, the data is not here yet. So you need to execute the code when you are sure the collection is ready. I usually listen to a "reset" event, and let the fetch to fire a reset event by collection.fetch({reset:true}).
Backbone Collection, whenever fetch, and get an array of data from server in a format
[obj1,obj2],
it will pass each of these into a parse function, described here
For debug purpose you can simply do:
var MyCollection=Backbone.Collection.extend({
parse:function(response){
console.log(response);
return response;
}
})
This can check if the fetch indeed get the json.
On a side note, it is always a good practise to fetch it after you initialized the collection, means you don't put the this.fetch() inside initialize(), you do this outside.
for example, if you want to print out all the element name, you can do
var c=MyCollection();
c.fetch({reset:true}); // this will fire 'reset' event after fetch
c.on('reset',printstuff());
function printstuff(){
_.forEach(c,function(e){
console.log(e.get('name'));
});
}
Note this 'reset' event fires after all the collection is set, means it is after the parse() function. Apart from this parse(), there is also a validate function that is called by model. You collection must have a model parameter, you can make your own model, and give it a validate(), it also print out stuff.

How to create an object of specific type from JSON in Parse

I have a Cloud Code script that pulls some JSON from a service. That JSON includes an array of objects. I want to save those to Parse, but using a specific Parse class. How can I do it?
Here's my code.
Parse.Cloud.httpRequest({
url: 'http://myservicehost.com',
headers: {
'Authorization': 'XXX'
},
success: function(httpResponse) {
console.log("Success!");
var json = JSON.parse(httpResponse.text);
var recipes = json.results;
for(int i=0; i<recipes.length; i++) {
var Recipe = Parse.Object.extend("Recipe");
var recipeFromJSON = recipes[i];
// how do i save recipeFromJSON into Recipe without setting all the fields one by one?
}
}
});
I think I got it working. You need to set the className property in the JSON data object to your class name. (Found it in the source code) But I did only try this on the client side though.
for(int i=0; i<recipes.length; i++) {
var recipeFromJSON = recipes[i];
recipeFromJSON.className = "Recipe";
var recipeParseObject = Parse.Object.fromJSON(recipeFromJSON);
// do stuff with recipeParseObject
}
Example from this page https://parse.com/docs/js/guide
var GameScore = Parse.Object.extend("GameScore");
var gameScore = new GameScore();
gameScore.save({
score: 1337,
playerName: "Sean Plott",
cheatMode: false
}, {
success: function(gameScore) {
// The object was saved successfully.
},
error: function(gameScore, error) {
// The save failed.
// error is a Parse.Error with an error code and message.
}
});
IHMO this question is not a duplicate of How to use Parse.Object fromJSON? [duplicate]
In this question the JSON has not been generated by the Parse.Object.toJSON function itself, but comes from another service.
const object = new Parse.Object('MyClass')
const asJson = object.toJSON();
// asJson.className = 'MyClass';
Parse.Object.fromJSON(asJson);
// Without L3 this results into:
// Error: Cannot create an object without a className
// It makes no sense (to me) why the Parse.Object.toJSON is not reversible

Parallel form submit and ajax call

I have a web page that invokes long request on the server. The request generates an excel file and stream it back to the client when it is ready.
The request is invoked by creating form element using jQuery and invoking the submit method.
I would like during the request is being processed to display the user with progress of the task.
I thought to do it using jQuery ajax call to service I have on the server that returns status messages.
My problem is that when I am calling this service (using $.ajax) The callback is being called only when the request intiated by the form submit ended.
Any suggestions ?
The code:
<script>
function dummyFunction(){
var notificationContextId = "someid";
var url = $fdbUI.config.baseUrl() + "/Promis/GenerateExcel.aspx";
var $form = $('<form action="' + url + '" method="POST" target="_blank"></form>');
var $hidden = $("<input type='hidden' name='viewModel'/>");
$hidden.val(self.toJSON());
$hidden.appendTo($form);
var $contextId = new $("<input type='hidden' name='notifyContextId'/>").val(notificationContextId);
$contextId.appendTo($form);
$('body').append($form);
self.progressMessages([]);
$fdbUI.notificationHelper.getNotifications(notificationContextId, function (message) {
var messageText = '';
if (message.IsEnded) {
messageText = "Excel is ready to download";
} else if (message.IsError) {
messageText = "An error occured while preparing excel file. Please try again...";
} else {
messageText = message.NotifyData;
}
self.progressMessages.push(messageText);
});
$form.submit();
}
<script>
The code is using utility library that invokes the $.ajax. Its code is:
(function () {
if (!window.flowdbUI) {
throw ("missing reference to flowdb.ui.core.");
}
function NotificationHelper() {
var self = this;
this.intervalId = null;
this.getNotifications = function (contextId, fnCallback) {
if ($.isFunction(fnCallback) == false)
return;
self.intervalId = setInterval(function() {
self._startNotificationPolling(contextId, fnCallback);
}, 500);
};
this._startNotificationPolling = function (contextId, fnCallback) {
if (self._processing)
return;
self._processing = true;
self._notificationPolling(contextId, function (result) {
if (result.success) {
var message = result.retVal;
if (message == null)
return;
if (message.IsEnded || message.IsError) {
clearInterval(self.intervalId);
}
fnCallback(message);
} else {
clearInterval(self.intervalId);
fnCallback({NotifyData:null, IsEnded:false, IsError:true});
}
self._processing = false;
});
};
this._notificationPolling = function (contextId, fnCallback) {
$fdbUI.core.executeAjax("NotificationProvider", { id: contextId }, function(result) {
fnCallback(result);
});
};
return this;
}
window.flowdbUI.notificationHelper = new NotificationHelper();
})();
By default, ASP.NET will only allow a single concurrent request per session, to avoid race conditions. So the server is not responding to your status requests until after the long-polling request is complete.
One possible approach would be to make your form post return immediately, and when the status request shows completion, start up a new request to get the data that it knows is waiting for it on the server.
Or you could try changing the EnableSessionState settings to allow multiple concurrent requests, as described here.

Add JSON value to ko.computed in viewmodel

I am busy creating a currency Module for my web app, I am using Yahoo Finance API to return the currency conversion rate of 2 currencies that I have defined in my local DB. I get the JSON data fine from the API, I just want to Bind the JSON data that I have received from the Finance API to my existing Viewmodel using ko.computed. I am not sure if I should be using ko.computed to achieve this, so any advice will help greatly.
Here is my code:
var currency = function (data) {
var self = this;
self.CurrencyFrom = ko.observable(data.CurrencyFrom);
self.CurrencyTo = ko.observable(data.CurrencyTo);
self.ConversionRate = ko.computed(rates); // I WANT TO BIND THE VALUE FROM API HERE
}
var CurrencyModel = function (Currencies) {
var self = this;
self.Currencies = ko.observableArray(Currencies);
self.AddCurrency = function () {
self.Currencies.push({
CurrencyFrom: "",
CurrencyTo: "",
ConversionRate: ""
});
};
self.RemoveCurrency = function (Currency) {
self.Currencies.remove(Currency);
};
self.Save = function (Form) {
alert("Could Now Save: " + ko.utils.stringifyJson(self.Currencies));
};
$.ajax({
url: "CurrencyConfiguration.aspx/GetConfiguredCurrencies",
// Current Page, Method
data: '{}',
// parameter map as JSON
type: "POST",
// data has to be POSTed
contentType: "application/json; charset=utf-8",
// posting JSON content
dataType: "JSON",
// type of data is JSON (must be upper case!)
timeout: 10000,
// AJAX timeout
success: function (Result) {
var MappedCurrencies =
$.map(Result.d,
function (item) {
getRate(item.CurrencyFrom, item.CurrencyTo);
return new currency(item);
}
);
self.Currencies(MappedCurrencies);
},
error: function (xhr, status) {
alert(status + " - " + xhr.responseText);
}
});
};
//3rd Party JSON result from Yahoo Finance API
function getRate(from, to) {
var script = document.createElement('script');
script.setAttribute('src', "http://query.yahooapis.com/v1/public/yql?q=select%20rate%2Cname%20from%20csv%20where%20url%3D'http%3A%2F%2Fdownload.finance.yahoo.com%2Fd%2Fquotes%3Fs%3D" + from + to + "%253DX%26f%3Dl1n'%20and%20columns%3D'rate%2Cname'&format=json&callback=rates"); //HERE I CALL THE VALUE TO OBTAIN THE CONVERSION RATE FROM API
document.body.appendChild(script);
}
//I WANT TO ADD THIS TO MY VIEWMODEL
var rates = function parseExchangeRate(YahooData) {
var rate = YahooData.query.results.row.rate;
}
$(document).ready(function () {
var VM = new CurrencyModel();
ko.applyBindings(VM);
$('[rel=tooltip]').tooltip();
})
The JSON returned from parseExchangeRate Function (Yahoo Query Result):
parseExchangeRate({"query":{"count":1,"created":"2013-01-18T06:46:41Z","lang":"en-US","results":{"row":{"rate":"0.1129","name":"ZAR to USD"}}}});
I see you're already using jquery so I'll use jquery for the JSONP too. I'm using a simple ko.observable for the conversion rate, and added a "bare" ko.computed that does the ajax request and asynchronously updates the observable. Let me know if you need any further clarification.
JSFiddle example (with mock data instead of your initial ajax): http://jsfiddle.net/VsW5H/1/
Updated code:
var currency = function (data) {
var self = this;
self.CurrencyFrom = ko.observable(data.CurrencyFrom);
self.CurrencyTo = ko.observable(data.CurrencyTo);
self.ConversionRate = ko.observable(data.ConversionRate);
ko.computed(function () {
var from = self.CurrencyFrom(),
to = self.CurrencyTo();
if (!from || !to) {
self.ConversionRate("N/A");
return;
}
getRate(from, to).done(function (YahooData) {
console.log("got yahoo data for [" + from + "," + to + "]: ", YahooData);
self.ConversionRate(YahooData.query.results.row.rate);
});
});
}
var CurrencyModel = function (Currencies) {
var self = this;
self.Currencies = ko.observableArray(Currencies);
self.AddCurrency = function () {
self.Currencies.push(new currency({
CurrencyFrom: "",
CurrencyTo: "",
ConversionRate: ""
}));
};
self.RemoveCurrency = function (Currency) {
self.Currencies.remove(Currency);
};
self.Save = function (Form) {
alert("Could Now Save: " + ko.utils.stringifyJson(self.Currencies));
};
$.ajax({
url: "CurrencyConfiguration.aspx/GetConfiguredCurrencies",
// Current Page, Method
data: '{}',
// parameter map as JSON
type: "POST",
// data has to be POSTed
contentType: "application/json; charset=utf-8",
// posting JSON content
dataType: "JSON",
// type of data is JSON (must be upper case!)
timeout: 10000,
// AJAX timeout
success: function (Result) {
var MappedCurrencies = $.map(Result.d,
function (item) {
return new currency(item);
});
self.Currencies(MappedCurrencies);
},
error: function (xhr, status) {
alert(status + " - " + xhr.responseText);
}
});
};
//3rd Party JSON result from Yahoo Finance API
function getRate(from, to) {
return $.getJSON("http://query.yahooapis.com/v1/public/yql?q=select%20rate%2Cname%20from%20csv%20where%20url%3D'http%3A%2F%2Fdownload.finance.yahoo.com%2Fd%2Fquotes%3Fs%3D" + from + to + "%253DX%26f%3Dl1n'%20and%20columns%3D'rate%2Cname'&format=json&callback=?");
}