Uncaught RefferenceError of global array in javascript - javascript

I have script in A.js like this:
function sinkronMyDB(){
sinkronDB();
var u_name = window.localStorage.getItem('uname');
if(dataSync.length !== 0){ // <-- line 4
var dataSinkronItems = [];
for (var i = 0; i<dataSync.length; i++) {
dataSinkronItems[i] = dataSync[i];
console.log('dataSync('+i+') = '+dataSync[i]);
};
$.ajax({
url:'http://qrkonfirmasi.16mb.com/delivery/update.php',
data: {data : dataSinkronItems, username: u_name},
type:'post',
async:'false',
dataType: 'json',
beforeSend:function(){
$.mobile.loading('show',{theme:"a",text:"Update...",textonly:true,textVisible:true});
},
complete:function(){
$.mobile.loading('hide');
},
success:function(result){
if (result.status===true) {
dataBaru = [];
idBaru = [];
for (i=0; i<dataBaru.length; i++){
dataBaru[i] = result.dataBaru[i];
idBaru[i] = result.id[i];
}
sinkronUpd();
console.log('Database update success.');
} else{
console.log('Tidak ada pengiriman baru.');
}
},
error:function(request,error){
alert('Koneksi error. Silahkan coba beberapa saat lagi!');
}
});
}else alert('Belum ada barang yang terkirim');
}
function sinkronDB() is in another Script file. lets call it B.js. the script content is like this:
function sinkronDB(){
db.transaction(sinkronQuery,errorCB);
}
function sinkronQuery(tx){
tx.executeSql("SELECT * FROM data_pengiriman WHERE Status = 'Terkirim'",[],successSelect);
}
function successSelect(tx,result){
var len = result.rows.length;
dataSync = [];
for (var i=0; i<len; i++){
dataSync[i] = result.rows.item(i).id_pengiriman;
console.log('dataSync['+i+'] = '+dataSync[i]);
}
}
In console log it's say error:
Uncaught ReferenceError: dataSync is not defined at file A.js line 4.
I tried check it with jshint and no error.
Can anyone help me solve it, please!

The problem is sinkronDB is asynchronous, so the if statement is evaluated before sinkronDB is completed
So you need to use a callback to handle the response like
function sinkronDB(callback) {
db.transaction(function (tx) {
sinkronQuery(tx, callback)
}, errorCB);
}
function sinkronQuery(tx, callback) {
tx.executeSql("SELECT * FROM data_pengiriman WHERE Status = 'Terkirim'", [], function (tx, result) {
successSelect(tx, result, callback);
});
}
function successSelect(tx, result, callback) {
var len = result.rows.length;
var dataSync = [];
for (var i = 0; i < len; i++) {
dataSync[i] = result.rows.item(i).id_pengiriman;
console.log('dataSync[' + i + '] = ' + dataSync[i]);
}
callback(dataSync)
}
then
function sinkronMyDB() {
sinkronDB(function (dataSync) {
var u_name = window.localStorage.getItem('uname');
if (dataSync.length !== 0) { // <-- line 4
var dataSinkronItems = [];
for (var i = 0; i < dataSync.length; i++) {
dataSinkronItems[i] = dataSync[i];
console.log('dataSync(' + i + ') = ' + dataSync[i]);
};
$.ajax({
url: 'http://qrkonfirmasi.16mb.com/delivery/update.php',
data: {
data: dataSinkronItems,
username: u_name
},
type: 'post',
async: 'false',
dataType: 'json',
beforeSend: function () {
$.mobile.loading('show', {
theme: "a",
text: "Update...",
textonly: true,
textVisible: true
});
},
complete: function () {
$.mobile.loading('hide');
},
success: function (result) {
if (result.status === true) {
dataBaru = [];
idBaru = [];
for (i = 0; i < dataBaru.length; i++) {
dataBaru[i] = result.dataBaru[i];
idBaru[i] = result.id[i];
}
sinkronUpd();
console.log('Database update success.');
} else {
console.log('Tidak ada pengiriman baru.');
}
},
error: function (request, error) {
alert('Koneksi error. Silahkan coba beberapa saat lagi!');
}
});
} else alert('Belum ada barang yang terkirim');
});
}

As the error message says, you have not defined dataSync.
Define it, var dataSync = []; and push whatever you need to it.

You have defined dataSync inside successSelect(tx,result) method, and it is not a global variable. sinkronMyDB() method has no access to it.
If you want to make it a global array, put var dataSync = [] outside the functions, and make sure successSelect(tx,result) method is executed before sinkronMyDB() method.

Related

Get property to array and write it to new array (JS)

I have code to get data from google api.
Here is the code:
$.ajax({
url: dburl,
dataType: 'json',
async: false,
type: 'GET',
data: model,
success: function (data) {
if (data.length !== 0) {
speeddata = data;
for (var i = 0; i < speeddata.length; i++) {
path = "path=" + speeddata[i].Latitude2 + ',' + speeddata[i].Longitude2;
var googleurl = "https://roads.googleapis.com/v1/speedLimits?"
+ path + "&key=" + roadsapikey;
$.ajax({
url: googleurl,
dataType: 'json',
async: false,
type: 'GET',
success: function(data) {
speedlimits = data;
console.log(speedlimits);
for (var i = 0; i < speedlimits.length; i++) {
speedobject.push({
speedlimits: speedlimits[i].speedLimits.speedLimit
});
}
console.log(speedobject);
}
});
}
}
},
error: function () {
alert("Error");
}
});
Here is what I get in response here - speedlimits
Response
I try to take speedLimit property and push it to new object.
Like this:
for (var i = 0; i < speedlimits.length; i++) {
speedobject.push({
speedlimits: speedlimits[i].speedLimits.speedLimit
});
}
But when I show speedobject in console it is empty.
Why so? Where is my problem?
The speedlimits object looks like this:
speedlimits = { // You're looping over this (speedlimits)
speedLimits: [ // You should be looping over this (speedlimits.speedLimits[i])
{speedLimit: 50},
// ...
],
snappedPoints: []
}
You are trying to loop over the speedLimits and snappedPoints items - not the elements within speedLimits.
for (var i = 0; i < speedlimits.speedLimits.length; i++) {
speedobject.push({
speedlimits: speedlimits.speedLimits[i].speedLimit
});
}
according to the data example here the api returns an object, not an array.. so your success function would look like this.. Make sure you get the case right too.
success: function(data) {
speedlimits = data.speedLimits;
console.log(speedlimits);
for (var i = 0; i < speedlimits.length; i++) {
speedobject.push({
speedlimits: speedlimits[i].speedLimit
});
}
console.log(speedobject);
}

Update textarea after get response from servlet in javascript

I have a program which calls a function in javascript with 1 o more requests to 1 servlet, I want to execute request after request and get the response after each exucution, to make this I have 1 function, but it only shows the result after all requests have been executed.
function cmd(args) {
width = 0;
var res = args.split('\n');
var largo = res.length;
var progressLength = 100 / largo;
for (var i = 0; i < largo; i++)
{
if (res[i] == 'desconectar')
{
desconectar();
break;
}
else
{
executeCMD(res[i]);
}
}
}
function executeCMD(args)
{
$.ajax({
type: "POST",
url: 'Controlador',
data: {cmd: args, operacion: 1},
success: function (response) {
document.getElementById('respuesta').value = document.getElementById('respuesta').value + response;
},
dataType: 'text',
async: false
});
}
If I add window.alert(response); inside success field it shows the progress step by step and works fine, but it show alerts which I don't want.
This is I want http://imgur.com/a/9nclR but I'm getting only last picture.
The solution if anyone is intersting was using a recursive function as next:
function cmd(args) {
width = 0;
move(0);
var res = args.split('\n');
var largo = res.length;
var valInit = 0;
if (largo > valInit)
{
executeCMD(res, valInit);
}
}
function executeCMD(args, i)
{
$(document).ready(function () {
$.ajax({
type: "POST",
url: 'ControladorServlet',
data: {cmd: args[i], operacion: 1, ticket: ticket, iddispositivo: sesion},
success: function (response) {
var textarea = document.getElementById('respuesta');
var res = response.trim().split('\n');
if(error){//dc}
else
{
document.getElementById('respuesta').value = document.getElementById('respuesta').value + response.trim() + "\n\n";
var valor = (100) * (i + 1) / args.length;
move(valor);
if (i + 1 < args.length)
{
executeCMD(args, i + 1);
}
}
},
dataType: 'text'
});
});
}

method is executing before ajax call getting completed

I am trying to call a method after all ajax calls gets completed but some reason the method id getting triggered before one of the ajax call is getting completed. i tried to keep the method in ajax complete section and using $.when() and async:false but i am getting same result. I don't know if its because i am using jsonp ?
My jquery version is 1.11.0
Below is my code
function getBBTrending() {
bbProductD = [];
jQuery.ajax({
type: "GET",
url: "crazycalls/getbbtrending.php",
// cache must be true
cache: true,
crossDomain: true,
success: function (data) {
bbTrending = data.results;
for (var i = 0; i < 4; i++) {
getProductdetails(bbTrending[i].productLink);
}
},
dataType: 'json'
});
}
function getProductdetails(pLink) {
jQuery.ajax({
type: "GET",
url: pLink,
// cache must be true
cache: true,
crossDomain: true,
success: function (data) {
pushArray(bbProductD, data);
},
dataType: 'jsonp'
});
}
function pushArray(array1,data1)
{
array1.push(data1);
}
// this function is executing before pushArray(array1,data1)
jQuery( document ).ajaxStop(function() {
displayProducts(bbProductD);
})
function displayProducts(bbProductD)
{
jQuery("#bbButtongroup").show();
var rProducts = bbProductD;
var rating;
var html = ['<div class="row">']
for (var i = 0; i < rProducts.length; i++)
{
var entry = rProducts[i];
var title = entry.name
var Tnail = entry.image;
var sPrice = entry.salePrice;
var rPrice = entry.regularPrice;
var hcode = '<div class="col-sm-6 col-md-4"><div class="thumbnail"><img style="height: 200px; width: 100%; display: block;" src=\" '+ Tnail + '\" alt="..."><div class="caption"><h3 style="font-size: 14px;">'+ title +'</h3><p><span class="label label-info"> Regular Price : '+ rPrice +'</span></p><p><span style="float: right;" class="label label-info">Sale Price :'+ sPrice +'</span></p><p>BuyView</p></div></div></div>';
html.push(hcode);
}
html.push('</div>');
document.getElementById('pContainer').innerHTML = html.join('');
}
this is how i added using $.when
jQuery.when( { getBBTrending(),getProductdetails()}).done(function() {
displayProducts(bbProductD);
});
any advice?
The asynchronous way, using async library
function getBBTrending() {
bbProductD = [];
jQuery.ajax({
//stuff...
success: function (data) {
bbTrending = data.results;
async.each(bbTrending, function(element, callback){
getProductdetails(element.productLink, callback);
}, function(err){
displayProducts(bbProductD);
});
},
});
}
function getProductdetails(pLink, callback) {
jQuery.ajax({
//stuff
success: function (data) {
pushArray(bbProductD, data);
callback(null);
},
});
}
The promises way, using jQuery.Deferred and jQuery.when
function getBBTrending() {
bbProductD = [];
jQuery.ajax({
//stuff...
success: function (data) {
bbTrending = data.results;
var promises = [];
for (var i = 0; i < bbTrending.length; i++) {
var promise = getProductdetails(bbTrending[i].productLink);
promises.push(promise);
}
jQuery.when.apply(jQuery, promises).then(function(){
displayProducts(bbProductD);
});
},
});
}
function getProductdetails(pLink) {
var promise = jQuery.Deferred();
jQuery.ajax({
//stuff
success: function (data) {
pushArray(bbProductD, data);
promise.resolve();
},
});
return promise;
}
The dirty way. I do not recommend this solution, it has many flaws. Try to use libraries when you need to do asynchronous stuff in order to keep your code maintainable.
var queriesCount, finishedQueriesCount;
function getBBTrending() {
bbProductD = [];
jQuery.ajax({
//stuff...
success: function (data) {
bbTrending = data.results;
queriesCount = 0;
finishedQueriesCount = 0;
for (var i = 0; i < bbTrending.length; i++) {
getProductdetails(bbTrending[i].productLink);
}
},
});
}
function getProductdetails(pLink) {
queriesCount++;
jQuery.ajax({
//stuff
success: function (data) {
pushArray(bbProductD, data);
finishedQueriesCount++;
if(queriesCount == finishedQueriesCount) {
displayProducts(bbProductD);
}
},
});
}
In each case, I pleaced the part of your code that is not significant for the answer by //stuff
Warning This answer has no error handling, it will fail (never call displayProducts(bbProductD);) if you have an ajax error.

jquery ajax not populating the drop down on first call

I have an input text box which fires each time when the user enters data and fills the input text.I'm using bootstrap typehead. Problem is when i enter a letter a it does fire ajax jquery call and fetch the data but the input text box is not populated.Now when another letter aw is entered the data fetched against letter a is filled in the text area.
I have hosted the code here http://hakunalabs.appspot.com/chartPage
Ok so here is part of my html code
<script type="text/javascript">
$(document).ready(function () {
$('#txt').keyup(function () {
delay(function () {
CallData();
}, 1000);
});
});
var delay = (function () {
var timer = 0;
return function (callback, ms) {
clearTimeout(timer);
timer = setTimeout(callback, ms);
};
})();
</script>
<input type="text" id="txt" runat="server" class="span4 typeahead local remote" placeholder="Search..." />
And here is my javascript code
var DataProvider;
function CallData() {
DataProvider = [];
var vdata = $('#txt').val();
if (vdata != "") {
var urlt = "http://examples/search?keyword=" + vdata + "&callback=my_callback";
$.ajax({
type: "GET",
url: urlt,
jsonpCallback: "my_callback",
dataType: "jsonp",
async: false,
error: function (xhr, errorType, exception) {
var errorMessage = exception || xhr.statusText;
alert("Excep:: " + exception + "Status:: " + xhr.statusText);
}
});
}
}
function my_callback(data) {
var NameArray = new Array();
var descArray = new Array();
for (var i = 0; i < data.count; i++) {
NameArray.push(data.response[i].days_till_close + " Days Left | " + data.response[i].name + " | " + data.response[i].description);
}
for (var i = 0; i < data.count; i++) {
descArray.push(data.response[i].description);
}
DataProvider = [];
for (var i = 0; i < data.count; i++) {
var dataObject = { id: i + 1, name: NameArray[i], description: descArray[i] };
DataProvider.push(dataObject);
}
var vdata = $('#txt').val();
var urlp = "http://example.com/v1/members/search?keyword=" + vdata + "&my_callbackMember";
$.ajax({
type: "GET",
url: urlp,
jsonpCallback: "my_callbackMember",
dataType: "jsonp",
error: function (xhr, errorType, exception) {
var errorMessage = exception || xhr.statusText;
alert("Excep:: " + exception + "Status:: " + xhr.statusText);
}
});
}
function my_callbackMember(data) {
var memberArray = new Array();
for (var i = 0; i < data.count; i++) {
memberArray.push(data.response[i].name);
}
for (var i = 0; i < data.count; i++) {
var dataObject = { id: i + 1, name: memberArray[i] };
DataProvider.push(dataObject);
}
localStorage.setItem("name", JSON.stringify(DataProvider));
var sources = [
{ name: "local", type: "localStorage", key: "name", display: "country" }
];
$('input.typeahead.local.remote').typeahead({
sources: [{ name: "", type: "localStorage", key: "name", display: "name"}],
itemSelected: function (obj) { alert(obj); }
});
}
Your issue is that typeahead can only present to you the results that are already in localstorage at the moment when you do a key press. Because your results are fetched via AJAX, they only show up in localstorage a second or so AFTER you've pressed the key. Therefore, you will always see the results of the last successful ajax requests in your typeahead results.
Read the bootstrap documentation for type aheads http://twitter.github.com/bootstrap/javascript.html#typeahead and read the section about "source". You can define a "process" callback via the arguments passed to your source function for asynchronous data sources.

Javascript processing and ASP.NET MVC

I have the following javascript and JsonResult. The issue I am having is the ajax post doesn't allow enough time for JsonResult to return the appropriate data. I probably don't completely understand javascript processing and I'm sure this is by design but I'm wondering how I can make this a synchronous request. In short, wait for the JsonResult action to complete before the javascript continues processing.
<script type="text/javascript">
$(document).ready(function () {
var table = document.getElementById("updateTable");
var tasks = new Array("shutdown", "prep", "boot", "ready");
var tasksLength = tasks.length;
for (var i in tasks) {
for (var loop = 1, max = table.rows.length; loop < max; loop++) {
id = table.rows[loop].cells[0].innerHTML;
task = tasks[i];
ImageUpdateStatus = {
ImageId: parseInt(id),
Task: task,
Status: "pending"
}
$.ajax({
type: "POST",
url: "UpdateStatus",
data: $.postify(ImageUpdateStatus),
success: function (data) {
var status = data.status;
}
});
ImageUpdateStatus.Status = status;
if (ImageUpdateStatus.Status == "success") {
task = task.concat(" ");
document.getElementById(task.concat(id)).src = "/PVSUtil_ver2/Assets/Images/Image.Success.png";
j = parseInt(i) + 1;
if (j < tasksLength) {
nextTask = tasks[j];
nextTask = nextTask.concat(" ");
document.getElementById(nextTask.concat(id)).src = "/PVSUtil_ver2/Assets/Images/Image.Load.gif";
}
}
}
}
document.getElementById('nextButton').className = "navigation";
document.getElementById('nextButton').disabled = false;
});
//
// GET: /Build/UpdateStatus
public JsonResult UpdateStatus(ImageUpdateStatus imageUpdateStatus, SessionStateItemCollection sessionItems = null)
{
var data = new object();
string status = null;
ImageInfo imageInfo = new ImageInfo();
IImageInfoServices svcImageInfo = new ImageInfoServicesRepository();
imageInfo = svcImageInfo.GetImageByImageId(imageUpdateStatus.ImageId);
IDeviceControlServices svcDevice = new DeviceControlServicesRespository();
IPVSCommandServices svcPVSCmds = new PVSCommandServicesRespository();
if (imageUpdateStatus.Task == "shutdown")
{
status = svcDevice.Shutdown(imageInfo.ImageId);
//status = "success";
data = new
{
status
};
}
if (imageUpdateStatus.Task == "prep")
{
List<UpdateReasonForm> updateReasonForms;
if (sessionItems.Keys.Count > 0)
{
updateReasonForms = sessionItems["UpdateReasonForms"] as List<UpdateReasonForm>;
}
else
{
updateReasonForms = Session["UpdateReasonForms"] as List<UpdateReasonForm>;
}
foreach (var item in updateReasonForms)
{
if (item.ImageId == imageInfo.ImageId)
{
status = svcPVSCmds.PrepImage(imageInfo, item.NewVersion);
}
}
data = new
{
status
};
}
if (imageUpdateStatus.Task == "boot")
{
status = svcDevice.Boot(imageInfo.ImageId);
data = new
{
status
};
}
if (imageUpdateStatus.Task == "ready")
{
status = "success";
data = new
{
status
};
}
return this.Json(data, JsonRequestBehavior.AllowGet);
}
Just move the code that relies on the result from the ajax request into the success callback function:
$.ajax({
type: "POST",
url: "UpdateStatus",
data: $.postify(ImageUpdateStatus),
success: function (data) {
ImageUpdateStatus.Status = data.status;
if (ImageUpdateStatus.Status == "success") {
task = task.concat(" ");
document.getElementById(task.concat(id)).src = "/PVSUtil_ver2/Assets/Images/Image.Success.png";
j = parseInt(i) + 1;
if (j < tasksLength) {
nextTask = tasks[j];
nextTask = nextTask.concat(" ");
document.getElementById(nextTask.concat(id)).src = "/PVSUtil_ver2/Assets/Images/Image.Load.gif";
}
}
}
});
You don't want to make the request synchronous; you want to put all code that depends on the result into your callback:
$.ajax({
type: "POST",
url: "UpdateStatus",
data: $.postify(ImageUpdateStatus),
success: function (data) {
var status = data.status;
ImageUpdateStatus.Status = status;
if (ImageUpdateStatus.Status == "success") {
task = task.concat(" ");
document.getElementById(task.concat(id)).src = "/PVSUtil_ver2/Assets/Images/Image.Success.png";
j = parseInt(i) + 1;
if (j < tasksLength) {
nextTask = tasks[j];
nextTask = nextTask.concat(" ");
document.getElementById(nextTask.concat(id)).src = "/PVSUtil_ver2/Assets/Images/Image.Load.gif";
}
}
}
});
$.ajax({
type: "POST",
async: false,
url: "UpdateStatus",
data: $.postify(ImageUpdateStatus),
success: function (data) {
var status = data.status;
}
});
but you really should avoid this, you should really look into making your application work with that wait for the ajax request
I really feel that you should aggregate any data you need to render your view for the first time on the server side and then push it down to the page. You could use JavaScript to do the rendering once the data is in the page (could be stored in JSON format in a hidden field) but I don't think it's optimal to have the page making an Ajax call when it's rendering for the first time.

Categories