How to set object property inside of function - javascript

I declare two object with name,link and page properties. After receiving data from Twitch API, I add a property status to my objects, which works inside the function, but leaving it I can't access status property anymore. I even tried to set the status property using getApi to return the status as streamer0.status=getApi(); but it does not work either.
var streamer0={name:"freecodecamp"};
streamer0.link='https://api.twitch.tv/kraken/streams/'+streamer0.name; streamer0.page='https://www.twitch.tv/'+streamer0.name;
var streamer1={name:"famasfordemacia"};
streamer1.link='https://api.twitch.tv/kraken/streams/'+streamer1.name;
streamer1.page='https://www.twitch.tv/'+streamer1.name;
var link="";
$(document).ready(function(){
load();
function load(){
for(var i=0;i<2;i++)
{
switch(i){
case 0:{
link=streamer0.link;
getApi(streamer0);
console.log(streamer0.status) //it does not work
break;
}
case 1:{
link=streamer1.link;
getApi(streamer1);
console.log(streamer1.status) //it does not work
break;
}
}
}
function getApi(x){
$.ajax({
type: 'GET',
url: link,
headers: {
'Client-ID': 'xxxxxxxxxxxxx'
},
success: function(data) {
if(data["stream"]==null)
{
x.status="offline";
console.log(x.status)//works
}
else
{
x.status="online";
}
}
});
}
});

You are Using Ajax , its asynchronous , so you have three options :
1 - put all you code inside the success callback which will be a big miss.
function getApi(x) {
$.ajax({
type: 'GET',
url: link,
headers: {
'Client-ID': 'xxxxxxxxxxxxx'
},
success: function (data) {
// ALL YOUR CODE IN HERE
}
});
}
2 - Using a callback function :
function getApi(x, callback) {
$.ajax({
type: 'GET',
url: link,
headers: {
'Client-ID': 'xxxxxxxxxxxxx'
},
success: function (data) {
// PASS YOUR DATA YOU THE CALL BACK
callback(data);
}
});
}
// THEN USE IT IN THE LOAD FUNCTION AS THE FOLLOWING
function load(){
for(var i=0;i<2;i++)
{
switch(i){
case 0:{
link=streamer0.link;
getApi(streamer0,function(data){
console.log(data.status) //it does not work
});
break;
}
case 1:{
link=streamer1.link;
getApi(streamer1,function(data){
console.log(data.status) //it does not work
});
break;
}
}
}
3 - is using Promise (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise).

It is a asynchronous call so you need wait until the call is done,
function getApi(x) {
return $.ajax({
type: 'GET',
url: link,
headers: {
'Client-ID': 'xxxxxxxxxxxxx' }});
case 0:{
link=streamer0.link;
getApi(streamer0).success(function(data){
if(data["stream"]==null)
{
streamer0.status="offline";
console.log(streamer0.status)//works
}
else
{
streamer0.status="online";
}
}
console.log(streamer0.status) //it does not work
});
break;
}
hope It helps you, :)

Related

Show waiting dialog on synchronous ajax

I want to show a waiting dialog while a synchronous ajax is made.
I using a Smart Wizard, to change between step one to step to i have to validate some data to do that i have to make 3 ajax call one after the other and while this is done i want to show a waiting dialog. This is what I'm doing.
if (indexes.fromStep==1) {
res=false;
var validatorResult = validator.checkAll($("#install_modbus_form"))
if (validatorResult) {
$("#modal_loader").modal()
$.ajax({
type: "post",
url: url1,
async: false,
dataType: "json",
data:{
data
},
success: function(response)
{
if (response.success)
{
$.ajax({
type: "post",
url: url2,
async: false,
dataType: "json",
data:{
data
},
success: function(response)
{
if (response.success)
{
$.ajax({
type: "post",
url: url3,
async: false,
dataType: "json",
data:{
data
},
success: function(response)
{
if (response.success)
{
//make magic here
res=true;
}
},
failure:function()
{
waitingDialog.hide()
res=false
},
error:function(a,b,c) {
waitingDialog.hide()
res=false
}
)
}
},
failure:function()
{
waitingDialog.hide()
res=false
},
error:function(a,b,c) {
waitingDialog.hide()
res=false
}
)
}
},
failure:function()
{
waitingDialog.hide()
res=false
},
error:function(a,b,c) {
waitingDialog.hide()
res=false
}
)
$("#modal_loader").modal('hide')
return res;//if true change step
}
}
I have trie use beforeSend to show the waiting dialog, also i have trie to use setTimeout but the waiting dialog is not show and the smart wizard dont go forward
Hope you can help, Im new in jquery.
Sorry for the bad english
On the assumption that you are using jQuery-Smart-Wizard, the solution lies in :
the construction of your onLeaveStep event handler, and (or including)
a modified version of the validation code shown in the question.
Fortunately, even though the plugin does not natively support asynchronism, it is fairly simple to make it do so. Essentially, what you need to do is :
to return false from the onLeaveStep callback,
to establish a promise which fulfills on successful validation, or rejects on failure,
to call .smartWizard('goForward') from the promise's success handler,
to call .smartWizard('showError') from the promise's error handler.
Based on smartWizard's ReadMe.md, here's a framework for performing synchronous and asynchronous validations :
$(document).ready(function() {
var waitingDialog = $('#whatever'); // ???
// Smart Wizard
$('#wizard').smartWizard({
onLeaveStep: leaveAStepCallback,
onFinish: onFinishCallback
});
function leaveAStepCallback(obj, context) {
alert("Leaving step " + context.fromStep + " to go to step " + context.toStep);
var returnValue;
switch(context.fromStep) {
case 1: // asynchronous
if (validator.checkAll($("#install_modbus_form"))) {
$("#modal_loader").modal();
waitingDialog.show();
validateStep1() // validateStep1() returns a promise
.then(function() {
// You will arrive here only if all three ajax calls were successful and all three responded with a truthy `response.success`.
$('#wizard').smartWizard('goForward'); // advance to next step
}, function(e) {
// You will arrive here on validation failure
$('#wizard').smartWizard('showError', e.message); // something went wrong
}).always(function() {
// You will arrive here on validation success or failure
waitingDialog.hide(); // the waiting is over
$("#modal_loader").modal('hide'); // ???
});
} else {
$('#wizard').smartWizard('showError', 'validator.checkAll() failed');
}
returnValue = false; // *must* return false to remain at step 1. If validation is successful, `.smartWizard('goForward')` will be executed later (see above).
break;
case 2: // synchronous
returnValue = validateStep2(); // validateStep2() returns true of false
break;
case 3:
...
break;
}
return returnValue; // true or false
}
// And here's the all-important `validateStep1()` :
function validateStep1() {
var sequence = [
{ url: 'url/1', data: {...} },
{ url: 'url/2', data: {...} },
{ url: 'url/3', data: {...} }
];
return sequence.reduce(function(promise, item, i) {
return promise.then(function() {
return $.ajax({
'type': 'post',
'url': item.url,
'dataType': 'json',
'data': item.data
}).then(function(response, textStatus, jqXHR) {
return response.success ? response : $.Deferred().reject(jqXHR, 'response.success not truthy at validation stage ' + i); // note: need to mimic jQuery.ajax's error signature.
});
});
}, $.when()) // starter promise for the reduction
.then(null, function(jqXHR, textStatus, errorThrown) {
return $.Deferred().reject(new Error(textStatus || errorThrown));
});
}
function validateStep2() {
// if validation here is synchronous, then return true of false
if(....) {
return true;
} else {
return false;
}
}
function validateStep3() {
...
}
// etc.
function onFinishCallback(objs, context) {
if(validateAllSteps()) {
$('form').submit();
}
}
function validateAllSteps() {
var isStepValid = true;
// all step validation logic
return isStepValid;
}
});
Notes :
the branching logic is in the onLeaveStep callback.
validateStep1() uses a chained promise pattern to sequence the three ajax calls.
if validateAllSteps() needs to repeat the step1 validation, then you will need call validateStep1().then(...) again, or chain from a previously cached promise.
As you can see, some aspects above are incomplete so there's still some work to do.

stopping a function after first click, to prevent more executions

I have this function
function display() {
$.ajax({
url: "new.php",
type: "POST",
data: {
textval: $("#hil").val(),
},
success: function(data) {
$('.daily').html(data);
}
});
}
and it serves its purpose, the only problem is, a user can click on for as many times as possible, and it will send just as many requests to new.php.
What I want is to restrict this to just 1 click and maybe till the next page refresh or cache clear.
Simple example would be :
<script>
var exec=true;
function display() {
if(exec){
alert("test");
exec=false;
}
}
</script>
<button onclick="javascript:display();">Click</button>
In your case it would be :
var exec=true;
function display() {
if(exec){
$.ajax({
url: "new.php",
type: "POST",
data: {
textval: $("#hil").val(),
},
success: function(data) {
$('.daily').html(data);
exec=false;
}
});
}
}
This should do what you want:
Set a global var, that stores if the function already was called/executed.
onceClicked=false;
function display() {
if(!onceClicked) {
onceClicked=true;
$.ajax({
url: "new.php",
type: "POST",
data: {
textval: $("#hil").val(),
},
success: function(data) {
$('.daily').html(data);
}
});
}
}
During onclick, set a boolean flag to true to indicate that user clicked the link before invoking the display() function. Inside the display() function, check the boolean flag and continue only if it is true. Reset the flag to false after the AJAX completed processing (successful or failed).
You can use Lock variable like below.
var lock = false;
function display() {
if (lock == true) {
return;
}
lock = true;
$.ajax({
url: "new.php",
type: "POST",
data: {
textval: $("#hil").val(),
},
success: function (data) {
$('.daily').html(data);
lock = false;
}
});
}
you can implement this with that way too
$(function() {
$('#link').one('click', function() {
alert('your execution one occured');
$(this).removeAttr('onclick');
$(this).removeAttr('href');
});
});
function display(){
alert('your execution two occured');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#" onclick="display();" id='link'>Have you only one chance</a>

External method from an AJAX callback in JavaScript & jQuery

I have a function in JS & jQuery that fires an AJAX call and it has a callback block to let me know when it's finished:
function ajaxCall(url, type, dataType, dataToSend, callback) {
if (dataType == undefined) dataType = "json";
if (dataToSend == undefined) dataToSend = null;
$.ajax({
url: url,
type: type,
dataType: dataType,
contentType: "application/json",
data: dataToSend,
async: true,
success: function (result) {
callback(result);
},
error: function (data, status) {
console.error("Server Error: " + status);
}
});
}
I am accessing it like so, but using external functions like showAjaxLoader() just doesn't work! it says this function is undefined:
function registerUser(data) {
ajaxCall(pathServiceRegister, "POST", undefined, JSON.stringify(data), function (result) {
// SOME CODE THAT RUNS WHEN IT'S COMPLETE
// External method:
showAjaxLoader(false); // Doesn't work
});
});
function showAjaxLoader(show) {
var loader = $('.ajax-loader');
if (show) {
loader.fadeIn("fast");
} else {
loader.fadeOut("fast");
}
}
What am I doing wrong?
Thanks :)
Worked out some sample. this may be good practice. Try this :
$(document).ready(function() {
$("button").click(function() {registerUser();});
});
var Scallback = function(arg) {
alert("Success :"+arg);
showAjaxLoader(true);
}
var Ecallback = function(arg) {
alert("Err :"+arg);
showAjaxLoader(true);
}
function showAjaxLoader(show) {
var loader = $('.ajax-loader');
if (show) {
loader.fadeIn("fast");
} else {
loader.fadeOut("fast");
}
}
function ajaxCall(url, type, Scallback, Ecallback) {
$.ajax({
url : url,
type : type,
async : true,
success : function(result) {
Scallback(result);
},
error : function(data) {
Ecallback(data)
}
});
}
function registerUser()
{
ajaxCall(pathServiceRegister, "GET", Scallback, Ecallback);
}
Have you tried to do something like:
var that = this;
function registerUser(data) {
ajaxCall(pathServiceRegister, "POST", undefined, JSON.stringify(data), function (result) {
// SOME CODE THAT RUNS WHEN IT'S COMPLETE
// External method:
that.showAjaxLoader(false);
});
});
Declare your method like this
var obj = {
showAjaxLoader : function(show) {
var loader = $('.ajax-loader');
if (show) {
loader.fadeIn("fast");
} else {
loader.fadeOut("fast");
}
}
}
Then inside ajax, call obj.showAjaxLoader(false); This may work.

2 responses from ajax call to php

In the code below i need 2 values from the response
Html response of the called page url
The value of the URL which was used to get the page OR the array index which was used in the call.
for (i = 0; i < pageURLs.length; i++) {
$.ajax({
url: pageURLs[i],
dataType: 'html',
statusCode: {
200: function(response) {
/*i am only getting access to the html of the page HERE*/
},
404: function() {
/*404 here*/
}
},
error: function(error) {
}
});}
EDIT Here is a more lightweight way of doing this, using let. See original response for explanation.
Notice This syntax might not be compatible with old browsers... :(
for (i = 0; i < pageURLs.length; i++) {
let j = i;
$.ajax({
url: pageURLs[j],
dataType: 'html',
statusCode: {
200: function(response) {
/* now you can also access j */
console.log("j=", j);
},
404: function() {
/*404 here*/
}
},
error: function(error) {
// error processing
}
});
}
Original answer
You need to wrap your loop body in a function, because the function scope will be preserved within the callback. Thus, you will be able to retrieve the correct i value within your callback.
for (i = 0; i < pageURLs.length; i++) {
(function(i) {
$.ajax({
url: pageURLs[i],
dataType: 'html',
statusCode: {
200: function(response) {
/*i am only getting access to the html of the page HERE*/
/* now you can also access i */
},
404: function() {
/*404 here*/
}
},
error: function(error) {
}});
}(i);
}

Ajax Request Loop and Wait Until Complete

Is there a more efficient way to write the following? I need to loop through objList and pass the UnqKey to wfrmPrint. On success of that I then have to loop though the Pages. I am looping through the pages and unqkeys by passing a integer and checking to see if it is less than the length. I tried to use .when.apply taken from http://www.tentonaxe.com/index.cfm/2011/9/22/Using-jQuerywhen-with-a-dynamic-number-of-objects, but it was loading the unqkeys and then the pages.
//sample objList
[
{
"UnqKey": 1,
"Pages": [
"wfrmSet1Page1.aspx",
"wfrmSet1Page2.aspx"
]
},
{
"UnqKey": 2,
"Pages": [
"wfrmSet2Page1.aspx",
"wfrmSet2Page2.aspx",
"wfrmSet3Page2.aspx",
"wfrmSet4Page2.aspx"
]
}
]
function Loop(iListIndex) {
var obj = objList[iListIndex];
if (iListIndex < objList.length) {
jQuery.ajax({
type: "GET",
url: 'wfrmPRINT.aspx?action=LoadSession&UnqKey=' + obj.UnqKey, //load session that is used in wfrmSet1Pages.. or wfrmSet2Pages..
success: function () {
AddPages(obj, iListIndex, 0);
}
})
} else {
alert('Done');
}
}
function AddPages(obj, iListIndex, iPageIndex) {
if (iPageIndex < obj.Pages.length) {
jQuery.ajax({
type: "GET",
url: obj.Pages[iPageIndex] + '?Print=1', //load html
async: true,
success: function (html) {
iPageIndex++
AddPages(obj, iListIndex, iPageIndex);
},
error: function () {
alert('Failed!');
iPageIndex++
AddPages(obj, iListIndex, iPageIndex);
}
});
} else {
iListIndex++
Loop(iListIndex);
}
}
You might be able to do something like this,
function getData(arr,arrindex) {
$.ajax({
type: "GET",
url: 'wfrmPRINT.aspx?action=LoadSession&UnqKey=' + arr[arrindex].UnqKey
}).then(function(data){
var deferredObj = $.Deferred(), defArr = $.map(arr[arrindex].Pages,function(page){
return $.ajax({type: "GET", url: page + '?Print=1'});
});
$.when.apply(null,defArr).done(deferredObj.resolveWith).fail(deferredObj.resolveWith);
return deferredObj.promise();
}).done(function(){
arrindex++;
if (arr[arrindex]) {
getData(arr,arrindex);
}
else {
alert("done!");
}
}).fail(function(){
alert("FAIL!");
});
}
getData(objList,0);
It gets each wfrm sequentially, and when each one finishes, requests all of the pages for that one at once. Somewhat of a combination between your loop and a deferred $.when
Edit: fixed $.map argument order

Categories

Resources