I did this function for get results of a query directly in an useful datastructure. The problem is the follow: in the first console.log() call , inside the callback function, the stored_data var contains the exact results, in the second console.log() call the stored_data variable looks like not initialized. Suggestions??
Below the code:
function dojo_query_mysql(query_string) {
//The parameters to pass to xhrPost, the message, and the url to send it to
//Also, how to handle the return and callbacks.
var stored_data;
var raw_data = new Object;
var xhrArgs = {
url: "query.php",
postData: query_string,
handleAs: "text",
load: function(data) {
raw_data = dojo.fromJson(data);
stored_data = new dojo.data.ItemFileReadStore({data: raw_data});
console.log(stored_data);
},
error: function(error) {
//We'll 404 in the demo, but that's okay. We don't have a 'postIt' service on the
//docs server.
//stored_data = error;
}
}
//Call the asynchronous xhrPost
var deferred = dojo.xhrPost(xhrArgs);
console.log(stored_data);
return stored_data;
}
I have just remembered that the function doesn't wait the end of the callback execution, for wait the callback end just do a little change to the code:
var xhrArgs = {
url: "query.php",
sync: true, // THIS IS FORCE THE SYNCRONIZATION BETWEEN THE CALLBACK AND THE CODE
postData: query_string,
handleAs: "text",
load: function(data) {
raw_data = dojo.fromJson(data);
stored_data = new dojo.data.ItemFileReadStore({data: raw_data});
console.log(stored_data);
},
error: function(error) {
//We'll 404 in the demo, but that's okay. We don't have a 'postIt' service on the
//docs server.
//stored_data = error;
}
}
Related
I have created an array in my VueComponent.
When I run a console.log(myArray.length) it says "0", however if I run a console.log(myArray) it shows that the array has the expected data. Check the screenshot from console below. The first part shows myArray, the second is myArray.length (circled in red)
See screenshot
Here is my current code:
Vue.component('invoice-archive', {
data: function () {
return {
invoices: [],
}
},
created() {
this.myUpdateMethod();
},
methods:{
myUpdateMethod: function(){
var $this = this;
let data = { 'id': installationId };
this.getAjax('myUrlHere', data).then(function (result) {
if(!result.length ) return; // <-- This was the problem
$this.invoices.push(JSON.parse(result));
console.log($this.invoices); // This shows the expected content of my array
console.log($this.invoices.length); // This shows 0
});
},
getAjax(url, data, success) {
return new Promise(function (resolve, reject) {
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
xhr.onload = function () {
resolve(this.responseText);
}
xhr.onerror = reject;
xhr.open('POST', url);
xhr.setRequestHeader('Content-Type', "application/json;charset=UTF-8");
xhr.send(JSON.stringify(data));
});
},
});
That is because when you are resolving the promise with this.responseText, you are passing a string into it. You will need to convert the response to JSON first, i.e.:
resolve(JSON.parse(this.responseText));
Since you're using VueJS, you might want to consider using axios instead of rolling your own AJAX request handler: https://v2.vuejs.org/v2/cookbook/using-axios-to-consume-apis.html
I was hoping to get a value (an object store) calling my dojo module, but I keep getting undefined :
module:
define(['dojo/store/Memory', 'dojo/_base/xhr', "dojo/data/ObjectStore"],
function (Memory, xhr, ObjectStore) {
var oReachStore;
return {
Reaches: function (url) {
xhr.get({//get data from database
url: url,
//url: url,
handleAs: "json",
load: function (result) {
var ReachData = result.GetReachesResult;
var ReachStore = new Memory({ data: ReachData, idProperty: "label" });
oReachStore = new ObjectStore({ objectStore: ReachStore });
},
error: function (err) { }
});
},
GetReaches: function () {
return oReachStore;
}
}
});
calls to module:
Data.Reaches(dataServiceUrl);//set the reach object store
ReachData = Data.GetReaches();//get the reach object store, but is always undefined
Like you probably noticed by now (by reading your answer), is that you're using an asynchronous lookup (the XMLHttpRequest is asynchronous in this case), but you're relying on that store, before it might be set.
A possible solution is the use of promises/deferreds. I don't know which Dojo version you're using, but in Dojo < 1.8 you could use the dojo/_base/Deferred module and since 1.8 you can use the dojo/Deferred module. Syntax is slightly different, but the concept is the same.
First you change the oReachStore to:
var oReachStore = new Deferred();
Then, inside your Reaches function you don't replace the oReachStore, but you use the Deferred::resolve() function, for example:
return {
Reaches: function (url) {
xhr.get({//get data from database
url: url,
//url: url,
handleAs: "json",
load: function (result) {
var ReachData = result.GetReachesResult;
var ReachStore = new Memory({ data: ReachData, idProperty: "label" });
oReachStore.resolve(ew ObjectStore({ objectStore: ReachStore })); // Notice the difference
},
error: function (err) { }
});
},
GetReaches: function () {
return oReachStore;
}
}
Then in your code you could use:
Data.Reaches(dataServiceUrl);//set the reach object store
Data.GetReaches().then(function(ReachData) {
console.log(ReachData); // No longer undefined
});
So now the ReachData won't return undefined, because you're waiting until it is resolved.
Deferreds are actually a common pattern in the JavaScript world and is in fact a more solid API compared to defining your own callbacks. For example, if you would get an error in your XHR request, you could use:
error: function(err) {
oReachStore.reject(err);
}
A simple example (I mocked the asynchronous request by using setTimeout()) can be found on JSFiddle: http://jsfiddle.net/86x9n/
I needed to use a callback function for the function GetReach. The following modified code worked:
Module:
define(['dojo/store/Memory', 'dojo/_base/xhr', "dojo/data/ObjectStore"],
function (Memory, xhr, ObjectStore) {
return {
GetReach: function (url, callback) {
xhr.get({//get data from database
url: url,
//url: url,
handleAs: "json",
load: function (result) {
var ReachData = result.GetReachesResult;
var ReachStore = new Memory({ data: ReachData, idProperty: "label" });
var oReachStore = new ObjectStore({ objectStore: ReachStore });
callback(oReachStore);
},
error: function (err) { }
});
}
}
});
call from main page:
// ....
Data.GetReach(dataServiceUrl, SetReach);
function SetReach(data) {
//set data for the dropdown
ddReach.setStore(data);
}
My question is very similar to this one which describes how to serve a local file using Iron Router. I need to do the same, but instead of reading the file synchronously from disk, I need to get the file from S3 which is an asynchronous call.
The problem appears to be the fact that the action method has returned before the asynchronous s3.getObject completes giving me the following error.
Error: Can't render headers after they are sent to the client.
I'm assuming that Iron Router is generating the response for me when it realizes that I haven't handled the response in my action method, but I'm stumped about how to tell it to wait for my asynchronous call to finish.
Here is my code.
Router.map(function () {
this.route('resumeDownload', {
where: 'server',
path: '/resume/:_id',
action: function () {
var response = this.response;
var candidate = Candidates.findOne(this.params._id);
if (!candidate || !candidate.resumeS3Key) {
// this works fine because the method hasn't returned yet.
response.writeHead(404);
return response.end();
}
var s3 = new AWS.S3();
s3.getObject({Bucket: 'myBucket', Key: candidate.resumeS3Key}, function (err, data) {
if (err) {
// this will cause the error to be displayed
response.writeHead(500);
return response.end();
}
// this will also cause the error to be displayed
response.writeHead(200, {'Content-Type': data.ContentType});
response.end(data.Body);
});
}
});
});
I was able to solve this one myself. I needed to use a future in my action method.
Here is the working code.
Router.map(function () {
this.route('resumeDownload', {
where: 'server',
path: '/resume/:_id',
action: function () {
var response = this.response,
candidate = Candidates.findOne(this.params._id);
if (!candidate || !candidate.resumeS3Key) {
response.writeHead(404);
return response.end();
}
var Future = Npm.require('fibers/future'),
s3 = new AWS.S3(),
futureGetObject = Future.wrap(s3.getObject.bind(s3)),
data = futureGetObject({Bucket: 'myBucket', Key: candidate.resumeS3Key}).wait();
response.writeHead(200, {'Content-Type': data.ContentType});
response.end(data.Body);
}
});
});
I'm studying Ember.js myself and I'm stuck with a problem I'm creating a sample app and I need to send the client side values to Server Side but I dont know how to do that I know the traditional way like the below code
function create() {
var data = {
'EmailID': $('#emailid').val(),
'password': $('#password').val()
}
$.ajax({
url: '/EmberNew/Home/Create',
type: 'POST',
data:data,
success: function (response) {
alert("hi");
}
});
return false;
}
but In Ember i dont Know How to do that my current code is given below
//Application
App = Em.Application.create();
//Model
App.Users = Em.Object.extend({
name: null,
password:null
});
//View
App.UserTextField = Em.TextField.extend({
insertNew: function () {
App.alertController.alertDetails();
}
});
App.PassTextField = Em.TextField.extend({
insertNew: function () {
App.alertController.alertDetails();
}
});
//controller
App.AlertController = Em.ObjectController.extend({
content: [],
username: '',
password: '',
alertDetails: function () {
var me = this;
var username = me.get("username");
var password = me.get("password");
alert('The User Name Is' + 'username' + 'And Password Is' + 'password');
}
});
App.alertController = App.AlertController.create();
I got the textbox values from alertDetails function and how can I pass them to server side
App.Record = Ember.Object.extend({
name: '',
other: ''
}).reopenClass({
records: [],
find: function() {
var self = this;
$.ajax({
url: "/api/records/",
type: "GET",
cache: false,
dataType: "json",
beforeSend: function() {
//if you want to call this often and need to clear + reload it
return self.records.clear();
},
success: function(results) {
var result;
for (_i = 0, _len = results.length; _i < _len; _i++) {
result = results[_i];
self.records.push(self.records.addObject(App.Record.create(result)));
}
},
error: function() {
return alert("error: failed to load the records");
}
});
return this.records;
}
});
Now that you have your model setup, you can call it from your route model hook
App.RecordsRoute = Ember.Route.extend({
model: function() {
return App.Record.find();
}
});
The find method returns an empty array right away, your template is then bound to it. When the ajax call returns w/ success and you update that array the handlebars template will update it for you w/out any DOM or jQuery glue code
//Below is my callback method which returns some response code.Now the thing is that i need to navigate to different view from the callback method.This logic i am using in userlogin. Provide me some solution that i can navigate to different view below i declared some code which i used to navigate to different view which works fine outside callback method not inside callback method.
Ext.data.JsonP.request({
url:'url',
method: 'POST',
callbackkey: 'callback',
params: {
userID: user_Id,
password: password,
format: 'json'
},
callback: function (response, value, request) {
//Logic should come here
}
else
{
}
},
failure: function (response, request) {
}
});
enter code here
//Below is the cofig entry
config: {
refs: {
homepage:'HP'
}
}
//I am adding below code in success block but getting error
var noteEditor = this.getHomepage();
Ext.Viewport.animateActiveItem(noteEditor, this.slideLeftTransition);
assuming you doing something like
Ext.data.JsonP.request({
url:'url',
method: 'POST',
callbackkey: 'callback',
params: {
userID: user_Id,
password: password,
format: 'json'
},
scope: this, /// fix handler scope
callback: function (response, value, request) {
if () {
//Logic should come here
var noteEditor = this.getHomepage();
Ext.Viewport.animateActiveItem(noteEditor, this.slideLeftTransition);
}
else
{
}
},
failure: function (response, request) {
}
});
you have to add a scope: this property to the ajax call.
Cheers, Oleg