In a button.click(function(){}); I have the following code:
var userId = $("#user-permission-edit").val();
var peId = $("#user-permission-entity-list").val();
var newParentPEId = $("#new-parent-pe").val();
var newPeName = $("#pe-name-add").val();
$.ajax({
type: "POST",
url: 'AddNewPE',
data: { 'targetUserId': userId, 'targetPEId': peId, 'newPeParentId': newParentPEId, 'newPeName': newPeName},
success: function (data) {
var dataObj = jQuery.parseJSON(data);
console.log(dataObj);
if (dataObj.status == "success") {
alert("Permissions have been updated.");
}
//update user PEs combo
}
});
However, I am concerned of a possible race condition of the variables not getting the values in time for the ajax call.
would something like this be safer?
var userId = $("#user-permission-edit").val();
var peId = $("#user-permission-entity-list").val();
var newParentPEId = $("#new-parent-pe").val();
var newPeName = $("#pe-name-add").val();
$.when(function() {
userId = $("#user-permission-edit").val();
peId = $("#user-permission-entity-list").val();
newParentPEId = $("#new-parent-pe").val();
newPeName = $("#pe-name-add").val();
}).done(function() {
$.ajax({
type: "POST",
url: 'AddNewPE',
data: { 'targetUserId': userId, 'targetPEId': peId, 'newPeParentId': newParentPEId, 'newPeName': newPeName},
success: function (data) {
var dataObj = jQuery.parseJSON(data);
console.log(dataObj);
if (dataObj.status == "success") {
alert("Permissions have been updated.");
}
//update user PEs combo
}
});
});
Is this even necessary?
The $('....').val() method is a synchronous call - your script execution won't continue past that line until you have received the value of that element.
Related
GetMandatoryFieldsforUser: function (data) {
var field = [];
$.get("api/mapping/mandatoryfield?type=USER", function (data) {
var self = this;
self.dt = [];
self.firmdata = JSON.parse(data.Data);
console.log(self.firmdata);
self.firmdata.forEach(function (item) {
field.push(item.DisplayName);
})
console.log(field) //able to print value
})
console.log(field) // not able to print value
return MandatoryFields.User;
},
EDIT
MandatoryFields = {
User: field,
}
my question here is i need to access field value outside forEach loop.How to achieve this using jquery or javascript
EDIT
"api/mapping/mandatoryfield?type=USER" returns
["First Name", "Last Name", "Location", "Email", "Password"],
see the edited question i want to use that field array inside MandatoryFields.User but if i use it its not showing the value
This implements $.ajax:
GetMandatoryFieldsforUser: function (data) {
var field = [];
$.ajax({
url: "api/mapping/mandatoryfield?type=USER"
}).done(function(data) {
// THIS PORTION IS EXECUTED AFTER DATA IS LOADED
var self = this;
self.dt = [];
self.firmdata = JSON.parse(data.Data);
console.log(self.firmdata);
self.firmdata.forEach(function (item) {
field.push(item.DisplayName);
})
console.log(field)
/*
USE return HERE!
*/
return field; // OR SOMETHING ELSE
})
// THIS WON'T WORK, BECAUSE DATA IS RETRIEVED IN ASYNC!
console.log(field)
},
Since $.get() is an asynchronous method, you can use async/await to access the returned value from the $.get method's callback.
GetMandatoryFieldsforUser: async function (data) {
var field = [];
const returnedField = await $.get("api/mapping/mandatoryfield?type=USER", function (data) {
var self = this;
self.dt = [];
self.firmdata = JSON.parse(data.Data);
console.log(self.firmdata);
self.firmdata.forEach(function (item) {
field.push(item.DisplayName);
})
console.log(field) //able to print value
return field;
}).promise()
console.log(returnedField) // not able to print value
},
You should use the ajax method in jquery.
function GetMandatoryFieldsforUser( data)
{
var field= [];
var scriptUrl = "api/mapping/mandatoryfield?type=USER";
$.ajax({
url: scriptUrl,
type: 'get',
dataType: 'html',
async: true,
success: function(data) {
var self = this;
self.dt = [];
self.firmdata = JSON.parse(data.Data);
console.log(self.firmdata);
self.firmdata.forEach(function (item) {
field.push(item.DisplayName);
})
console.log(field)
}
});
return field;
}
i'm really struggling to understand the asynchronous side of JavaScript. the code i have is meant to collate specific details of certain users and then put all the collated information into a global variable array which i intent to manipulate when all the users have been added to the array. i'm finding it difficult to iterate the array because when i do an array.length on the printurlonPage() function i get a 0 despite the fact that when i do a console log on the array itself i can see that there are items there. Does anyone know a technique that allows me to work on the global variable only after the asynchronous function has completed?
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
var PeopleCompleteList = [];
function PersonConstructor(username,Title,Phone,Email,imageurl){
return {
name: username,
Title: Title,
phoneNumber: Phone,
Email: Email,
Picture: imageurl
}
}
var printurlonPage = function (){
for (var link in PeopleCompleteList) {
console.log(link['Picture']);
}
console.log(PeopleCompleteList);
}
var getIndividualPersonDetails = function(GetPictureUrl) {
listName = 'TeamInfo';
//var PeopleCompleteList = [];
// execute AJAX request
$.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('"+listName+"')/items?$select=Name/Title,Name/Name,Name/Id,Name/EMail,Name/WorkPhone&$expand=Name/Id",
type: "GET",
headers: { "ACCEPT": "application/json;odata=verbose" },
success: function (data) {
for (i=0; i< data.d.results.length; i++) {
//check if the user exists if he does store the following properties name,title,workphone,email and picture url
if(data.d.results[i]['Name'] != null){
var personName = data.d.results[i]['Name'].Name.split('|')[2];
var userName = data.d.results[i]['Name']['Name'];
var UserTitle = data.d.results[i]['Name']['Title'];
var UserphoneNumber = data.d.results[i]['Name']['WorkPhone'];
var UserEmail = data.d.results[i]['Name']['EMail'];
var myuserPicture = GetPictureUrl(userName);
console.log(myuserPicture);
PeopleCompleteList.push(PersonConstructor(personName, UserTitle, UserphoneNumber,UserEmail,myuserPicture));
}
}
},
error: function () {
alert("Failed to get details");
}
});
}
function GetPictureUrl(user) {
var userPicture="";
var requestUri = _spPageContextInfo.webAbsoluteUrl +
"/_api/SP.UserProfiles.PeopleManager/GetPropertiesFor(accountName=#v)?#v='"+encodeURIComponent(user)+"'";
$.ajax({
url: requestUri,
type: "GET",
async:false,
headers: { "ACCEPT": "application/json;odata=verbose" },
success: function (data) {
console.log(data);
var PictureDetails = data.d.PictureUrl != null ? data.d.PictureUrl : 'c:\apps\noimageurl.jpg';
userPicture=PictureDetails;
}
});
return userPicture;
};
$(function () {
getIndividualPersonDetails(GetPictureUrl);
printurlonPage();
});
</script>
You're printurlonPage() is not asynchronous, so it's running before getIndividualPersonDetails responds. You can do two things, use promises or use async/await from es7. I prefer async/await, but you'll need to babelify.
Or, you can just put your printurlonPage invocation inside your success: handler.
success: function (data) {
for (i=0; i< data.d.results.length; i++) {
//check if the user exists if he does store the following properties name,title,workphone,email and picture url
if(data.d.results[i]['Name'] != null){
var personName = data.d.results[i]['Name'].Name.split('|')[2];
var userName = data.d.results[i]['Name']['Name'];
var UserTitle = data.d.results[i]['Name']['Title'];
var UserphoneNumber = data.d.results[i]['Name']['WorkPhone'];
var UserEmail = data.d.results[i]['Name']['EMail'];
var myuserPicture = GetPictureUrl(userName);
console.log(myuserPicture);
PeopleCompleteList.push(PersonConstructor(personName, UserTitle, UserphoneNumber,UserEmail,myuserPicture));
}
}
printurlonPage();
},
And then in document.ready:
$(function () {
getIndividualPersonDetails(GetPictureUrl);
});
So, getIndividualPersonDetails is invoked, and then when it receives the data, the callback is invoked with the data.
On my code I hava a function with 3 nested AJAX calls, in order for it to work I had to set Async=false.
As I have read that Async=false is deprecated I replaced the Async=false with promises.
This is my function before I edited it:
self.getOrders = function (name) {
var orders= [];
var order= function (item, type1, type2) {
var self = this;
self.order= item;
self.type1= type1;
self.type2= type2;
}
$.ajax({
url: "/API/orders/" + name,
type: "GET",
async: false,
success: function (orderResults) {
var mappedOrders = $.map(orderResults, function (orderItem) {
$.ajax({
url: "/API/orders/property/" + orderItem.id + "/type1",
type: "GET",
async: false,
success: function (property1Results) {
$.ajax({
url: "/API/orders/property/" + orderItem.id + "/type2",
type: "GET",
async: false,
success: function (property2Results) {
orders.push(new order(orderItem, property1Results, property2Results));
}
});
}
});
})
}
});
return orders;
This function worked perfectly, I got the data end everything worked fine.
Then I changed the function to use promises instead of Async=false,
this is the edited function, with promises:
//The begin of the function- same as first one
var orders= [];
var firstPromise = $.ajax({
url: "/API/orders/" + name,
type: "GET"
});
$.when(firstPromise).done(function (orderResults) {
var mappedOrders = $.map(orderResults, function (orderItem) {
var secondPromise = $.ajax({
url: "/API/orders/property/" + orderItem.id + "/type1",
type: "GET"
});
$.when(secondPromise).done(function (property1Results) {
var thirdPromise = $.ajax({
url: "/API/orders/property/" + orderItem.id + "/type2",
type: "GET"
});
$.when(thirdPromise).done(function (property2Results) {
orders.push(new order(orderItem, property1Results, property2Results));
});
});
});
});
return orders;
And the function call:
self.populateOrders = function (name) {
var mappedOrders = $.map(self.service.getOrders(name), function (item) {
return new Order(item)
});
self.orders(mappedOrders);
}
The new function is not working, I'm getting back from the firstPromise a wrong json with backslashes, and the returned orders object is empty.
Any idea what am I doing wrong? I spent so much time on it but couldn't figure it out.
Thanks in advance.
Nested ajax calls inside a loop is a hell to manage. You can do it like this.
Create a promise to notify the caller when the whole process is finished
Wait for all the inner ajax calls to resolve
Resolve you main promise to notify the caller
self.getOrders = function (name) {
var mainDeferred = $.Deferred();
var orders = [];
var order = function (item, type1, type2) {
var self = this;
self.order = item;
self.type1 = type1;
self.type2 = type2;
}
$.ajax({
url: "/API/orders/" + name,
type: "GET",
success: function (orderResults) {
var innerwait = [];
var mappedOrders = $.map(orderResults, function (orderItem) {
var ajax1 = $.ajax({
url: "/API/orders/property/" + orderItem.id + "/type1",
type: "GET"
});
var ajax2 = $.ajax({
url: "/API/orders/property/" + orderItem.id + "/type2",
type: "GET"
});
$.when(ajax1, ajax2).done(function (property1Results, property2Results) {
orders.push(new order(orderItem, property1Results[0], property2Results[0])))
});
innerwait.push(ajax1, ajax2);
});;
$.when.apply(null, innerwait) //make sure to wait for all ajax requests to finish
.done(function () {
mainDeferred.resolve(orders); //now that we are sure the orders array is filled, we can resolve mainDeferred with orders array
});
}
});
return mainDeferred.promise();
}
self.populateOrders = function (name) {
self.service.getOrders(name).done(function (orders) { //use .done() method to wait for the .getOrders() to resolve
var mappedOrders = $.map(orders, function (item) {
return new Order(item)
});
self.orders(mappedOrders);
});
}
In the example, note that I use $.when.apply() to wait for an array of deferreds.
A bug recently introduced in chrome 52 (august 2016) can cause this kind of behavior : answers for nested requested are ignored.
Hoppefully, it will not last long.
https://bugs.chromium.org/p/chromium/issues/detail?id=633696
Try to add cache: false
I have a javascript function
function TxEncrypt(event)
{ //perform encryption of token data, then submit the form like normal
//obtain public key and initial JSEncrypt object
var txPubKey = txJ$(".zwitch_encryptionkey").val();
var txEncrypter = new JSEncrypt();
txEncrypter.setPublicKey(txPubKey);
//get Data and encrypt it
var txData = '{}';
var txCryptData = '';
if(txJ$(".zwitch_data").length > 1)
{ //if there are more than one element with this class, convert it to json string
txData = txJ$(".zwitch_data").serializeObject();
txCryptData = txEncrypter.encrypt(JSON.stringify(txData));
}
else
{ //else, just encrypt the value
txData = txJ$(".zwitch_data").val();
txCryptData = txEncrypter.encrypt(txData);
}
dataString = txCryptData; // array?
$.ajax({
type: "POST",
url: "tokenize.php",
data: {data : dataString},
cache: false,
success: function(data) {
returnedvalue = data;
console.log(data); //alert isn't for debugging
}
});
alert(dataString);
}
I could get the value of dataString.But the ajax parrt is not working.I have added the jquery library.But doesnt seem to work
What's the error you are getting?
I think this should be:
$.ajax({
type: "POST",
url: "tokenize.php", //removed the dot
.....
i try to get a function return in combination with facebook api reqeust.
var g_ret = true;
function uploadImagesFbCounter(anz){
var gid='';
$("div[id ^= 'gallerydetail']").each(function (i) {
gid = this.id.split('-');
gid = parseInt(gid[1]);
})
if(gid==0) return true;
FB.api('/me', function(response) {
//console.log(response);
var uid = response.id;
if(!anz){
g_ret = $.ajax({
type: "POST",
async:false,
url: "api/gallerie_anz_speich.php",
data: "uid="+uid+"&op=get&gid="+gid
});
if(g_ret.response >= 20) {
g_ret = false;
}
} else {
g_ret = $.ajax({
type: "POST",
async:false,
url: "api/gallerie_anz_speich.php",
data: "uid="+uid+"&op=set&gid="+gid
});
//console.log(g_ret.response);
g_ret = '<span style="padding:0 5px;">Noch '+(20-g_ret.response)+'Fotos</span>';
console.log(g_ret);
}
});
return g_ret;
}
what ever I do, i get an empty response.... please help!
The API you're using is asynchronous. You can't return a value from your function like that; it's just impossible in such a situation.
Instead, write your API so that its clients pass it a callable function. Inside the Facebook API callback, you can call that function and pass it that "g_ret" string.
function uploadImagesFbCounter(anz, callback){
// ...
FB.api('/me', function(response) {
// ...
callback(g_ret);
});
}
Then when you call your function, instead of:
var result = uploadImagesFbCounter( whatever );
// ... do something with result ...
you'd do this:
uploadImagesFbCounter( whatever, function( result ) {
// ... do something with result ...
});
Getting the user information from Facebook's servers is asynchronous. This means, any code you write after FB.api() does not wait for Facebook to respond. Your browser is not blocked just to wait for Facebook's servers. This is the same concept as AJAX, which I believe you are familiar with because I see you use it in your code.
The common way to "get a return value" from an asynchronous server request is to use a callback function.
function uploadImagesFbCounter(anz, onSuccess){
var gid='';
$("div[id ^= 'gallerydetail']").each(function (i) {
gid = this.id.split('-');
gid = parseInt(gid[1]);
})
if(gid==0) return true;
FB.api('/me', function(response) {
//console.log(response);
var uid = response.id;
if(!anz){
g_ret = $.ajax({
type: "POST",
async:false,
url: "api/gallerie_anz_speich.php",
data: "uid="+uid+"&op=get&gid="+gid
});
if(g_ret.response >= 20) {
g_ret = false;
}
} else {
g_ret = $.ajax({
type: "POST",
async:false,
url: "api/gallerie_anz_speich.php",
data: "uid="+uid+"&op=set&gid="+gid
});
//console.log(g_ret.response);
g_ret = '<span style="padding:0 5px;">Noch '+(20-g_ret.response)+'Fotos</span>';
console.log(g_ret);
}
onSuccess(g_ret);
});
}
uploadImagesFbCounter(
whateverAnzIs,
function(g_ret) {
console.info(g_ret);
}
);