Ajax promise not working - javascript

I'm trying to use promise to return a comparison of current logged in user and a field from a list in SharePoint.
function compareCurrentUserWithListObject() {
var userProp = this._userProfileProperties;
var userName = userProp.get_userProfileProperties()['UserName'];
return this._list.filter(function (element, index, array) {
var promise = jQuery.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/GetUserById(" + element.user.get_lookupId() + ")",
type: "GET",
headers: { "Accept": "application/json;odata=verbose" }
});
promise.done(function(data) {
return (data.d.Email.indexOf(userName) > -1);
});
});
}
function init() {
var userArray = this.compareCurrentUserWithListObject();
userArray.done(function(res) {
if (res.length > 0) {
//Do some stuff after compare...
}
});
}
I'm not sure I'm using the .done correct here. Can someone help me?
EDIT:
Working code:
function compareCurrentUserWithListObject() {
var userProp = this._userProfileProperties;
var userName = userProp.get_userProfileProperties()['UserName'];
return this._list.filter(function (element, index, array) {
var promise = jQuery.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/GetUserById(" + element.user.get_lookupId() + ")",
type: "GET",
headers: { "Accept": "application/json;odata=verbose" }
});
promise.done(function(data) {
return (data.d.Email.indexOf(userName) > -1);
});
return promise;
});
}
function init() {
var userArray = this.compareCurrentUserWithListObject();
if (userArray.length > 0) {
//Do some stuff after compare...
}
}

you need to return the promise
function compareCurrentUserWithListObject() {
var userProp = this._userProfileProperties;
var userName = userProp.get_userProfileProperties()['UserName'];
return this._list.filter(function (element, index, array) {
var promise = jQuery.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/GetUserById(" + element.user.get_lookupId() + ")",
type: "GET",
headers: { "Accept": "application/json;odata=verbose" }
});
promise.done(function(data) {
return (data.d.Email.indexOf(userName) > -1);
});
// return promise here
return promise;
});
}
or this (which is cleaner IMO):
function compareCurrentUserWithListObject() {
var userProp = this._userProfileProperties;
var userName = userProp.get_userProfileProperties()['UserName'];
return jQuery.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/GetUserById(" + element.user.get_lookupId() + ")",
type: "GET",
headers: { "Accept": "application/json;odata=verbose" }
});
}
function init() {
this.compareCurrentUserWithListObject()
.done(function(data) {
var res = data.d.Email.indexOf(userName) > -1;
if (res.length > 0) {
//Do some stuff after compare...
}
});
}
it looks like you want to modify the response before using it in init. There is a way to do that but I'd do it inside the .done callback when using it.
I didn't test this code so there might be mistakes. But the general answer is: you need to return the promise.

The idiomatic way to do this using promises is to use Promise.all(). (I'll use Q promises as an example, but Promise.all is built into the JS6 promise API and several other promise libraries):
function getUserInfo(listItem) {
var promise = jQuery.ajax({
url: _spPageContextInfo.webAbsoluteUrl +
"/_api/web/GetUserById(" + listItem.user.get_lookupId() + ")",
type: "GET",
headers: { "Accept": "application/json;odata=verbose" }
});
return Q.Promise.when(promise);
}
function filterUsers(users) {
var userProp = this._userProfileProperties;
var userName = userProp.get_userProfileProperties()['UserName'];
return users.filter(function (user) {
return user.d.Email.indexOf(userName) > -1;
});
}
function init() {
Q.Promise.all(this._list.map(getUserInfo))
.then(filterUsers.bind(this))
.then(function (matchedUsers) {
// matchedUsers is an array of all the users you want.
// use it as needed
});
}

Related

How do I confirm a 100% Redirect through Javascript by using async await

I am trying to redirect to another server call but unfortunately browser sometimes redirect or sometime just refresh the current page.
Redirect is in getCheckOutOfHrs async function and I tried all three options
1). window.location = myurl;
2). window.location.href = myurl;
3). window.location.assing(myurl);
4). window.location.replace(myurl);
Nothing is 100% a working solution in my case. sometimes browser redirects and sometimes not.
I don't know why browser is doing this. see my tried code is below.
I am trying to use async function.
$('#btn-search-car').click(function(e) {
searchCar(e)
});
function searchCar(e) {
try {
//debugger;
e.preventDefault();
var obj = {
Branch: lStrLocNam.trim(),
PickupLocId: lIntPickupLocId,
FranchiseId: lIntFranchiseId,
SubofficeId: lIntSubofficeId,
StartDate: dtStart /*startDate*/ ,
StartTime: startTime,
EndDate: dtEnd /*endDate*/ ,
EndTime: endTime,
VehicleType: selectedVehType,
VehicleCategoryId: carCat,
IsNewSearch: true
};
saveElement('SelectedParamInSearch', obj);
let apiUrl = REACT_APP_CheckOutOfHours;
getCheckOutOfHrs(obj);
} catch (err) {
//hideProgress();
}
};
const getCheckOutOfHrs = async(obj) => {
let abortController = new AbortController();
let lattitude = 0;
let longitude = 0;
let resultPages = [];
let apiUrl = REACT_APP_CheckOutOfHours;
const settings = {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(obj),
signal: abortController.signal
};
const responseDetail = await fetch(apiUrl, settings);
//abortController.abort();
if (responseDetail && !responseDetail.ok) {
resultPages = [];
} else {
resultPages = await responseDetail.json();
}
try {
let OutOfHours = resultPages; //? JSON.parse(resultPages):'';
//debugger;
debugger;
if (OutOfHours) {
saveElement('OutOfHoursParam', OutOfHours);
//OutOfHours = OutOfHours.replace('"', '').replace('"', '');
if (OutOfHours.length != 0 && OutOfHours.item2 && OutOfHours.item2.indexOf("£") > 0) {
//window.location = "/Home/FindBranch/?franchiseId=" + obj.FranchiseId;
let redirectLocalUrl = "/Home/FindBranch/?franchiseId=" + obj.FranchiseId;
window.location.replace(redirectLocalUrl);
// window.location.href = redirectLocalUrl;
// windowtruelocation.assign(redirectLocalUrl);
return false;
/* $.ajax({
url: "/Home/FindBranch",
data: obj,
success: function (data) {
window.location.href = "/Home/FindBranch";
},
dataType: "html",
type: "POST",
cache: false,
error: function () {
}
}); */
} else if (OutOfHours.length != 0 && OutOfHours.item2 && OutOfHours.item2.indexOf("£") < 0) {
//OutOfHours = OutOfHours.replace("\\", "'").replace("\\", "");
alert(OutOfHours.item2);
return false;
} else {
//FindBranch
//window.location = "/Home/FindBranch/?franchiseId=" + obj.FranchiseId;
let redirectLocalUrl = "/Home/FindBranch/?franchiseId=" + obj.FranchiseId;
window.location.replace(redirectLocalUrl);
// window.location.href = redirectLocalUrl;
// window.location.assign(redirectLocalUrl);
return true;
/* $.ajax({
url: "/Home/FindBranch",
data: obj,
success: function (data) {
// debugger;
window.location.href = "/Home/FindBranch";
//hideProgress();
},
dataType: "html",
type: "POST",
cache: false,
error: function () {
// hideProgress();
}
}); */
}
}
} catch (error) {
debugger;
}
};
Help is appreciated.

JavaScript Function ReEntrant in promise object

I would like to reentrant function in promise object.
this function contains Asynchronous processing.
however, this function dose NOT Work.
To be specified, DOES NOT fired ,next "then method".
the code is here
loopcount = 0;
getItemcount = 0;
global_ItemCol = [];
function GetItem_in_List_Over5000(parentSiteUrl, listGuid)
{
if (loopcount == 0) {
console.log("Enter FirstTime");
endPoint = parentSiteUrl + "/_api/Web/Lists(guid'" + listGuid + "')/Items?$top=3000&$select=Title,Id,ContentTypeId,HasUniqueRoleAssignments";
} else {
console.log("Eneter SecondTime");
}
return new Promise(function (resolve_GetItem_in_List5000, reject_GetItem_in_List5000) {
console.log("Eneter Inner Function");
$.ajax({
type: 'GET',
url: endPoint,
headers: { 'accept': 'application/json;odata=verbose', "X-RequestDigest": $("#__REQUESTDIGEST").val() },
success: function (data) {
console.log(data.d.__next);
if (data.d.__next) {
global_ItemCol = global_ItemCol.concat(data.d.results);
endPoint = data.d.__next;
loopcount++;
console.log("looopcount increment. " + global_ItemCol.length);
GetItem_in_List_Over5000(parentSiteUrl, listGuid);
} else {
global_ItemCol = global_ItemCol.concat(data.d.results);
var local_col = [];
local_col = local_col.concat(global_ItemCol);
loopcount = 0;
global_ItemCol.length = 0;
resolve_GetItem_in_List5000(local_col);
console.log("return call");
//return Promise.resolve().then(local_col);
resolve_GetItem_in_List5000(local_col);
}
},
error: function (error) {
OutputLog(error.responseJSON.error.message.value);
loopcount = 0;
reject_GetItem_in_List5000();
}
});
});
}
I called this function Added Array and Promise.All().
Thanks in advance.
You could try a recursive function. Store results in an array (not global but pass it to the recursive function). With every result set store the guid so you know what result set came from what guid (when requests start failing you know what you've done so far).
function GetItem_in_List_Over5000(parentSiteUrl, listGuid) {
const recur = (listGuid,results=[]) =>
$.ajax({
type: 'GET',
url: parentSiteUrl + "/_api/Web/Lists(guid'" + listGuid + "')/Items?$top=3000&$select=Title,Id,ContentTypeId,HasUniqueRoleAssignments",
headers: { 'accept': 'application/json;odata=verbose', "X-RequestDigest": $("#__REQUESTDIGEST").val() },
}).then(
function (data) {
console.log(data.d.__next);
if (data.d.__next) {
return recur(
data.d.__next,
results.concat([listGuid,data.d.results])
);
} else {
//add listGuid to result set so you know where it came from
return results.concat([listGuid,data.d.results]);
}
}
).fail(//newer jQuery can use .catch
err=>({type:"error",error:err,results:results})
);
return recur(listGuid)
}
GetItem_in_List_Over5000("url","guid")
.then(
results=>{
if((results&&results.type)===error){
console.log("something went wrong:",results.error);
console.log("have some results:",results.results);
}else{
console.log("got all results:",results);
}
}
)

Second promise is not working properly

I have the following promise that works perfectly:
self.getAll = function (callback) {
var users= [];
var promises = [];
$.ajax({
url: "/API/Users",
type: "GET",
success: function (results) {
var mappedContacts = $.map(results, function (item) {
promises.push($.ajax({
url: "/API/Users/contacts/" + item.id,
type: "GET"
}).then(function (contacts) {
users.push(new User(item, contacts));
}));
});
$.when.apply($, promises).then(function () {
callback(users);
});
}
});
}
I'm trying to add a second AJAX request but it's not working properly:
self.getAll = function (callback) {
var users= [];
var promises = [];
$.ajax({
url: "/API/Users",
type: "GET",
success: function (results) {
var mappedContacts = $.map(results, function (item) {
promises.push($.ajax({
url: "/API/Users/contacts/" + item.id,
type: "GET"
}).then(function (contacts) {
users.push(new User(item, contacts));
}));
});
var mappedContacts2 = $.map(results, function (item) {
promises.push($.ajax({
url: "/API/Users/contacts2/" + item.id,
type: "GET"
}).then(function (contacts2) {
users.push(new User(item, "",contacts2));
}));
});
$.when.apply($, promises).then(function () {
callback(users);
});
}
});
}
contacts2 is always empty, what am I doing wrong?
This is the User object:
var User= function (data, contacts, contacts2) {
this.id = ko.observable(data.id);
this.name = ko.observable(data.name);
this.contacts = ko.observableArray(contacts);
this.contacts2 = ko.observableArray(contacts2 );
}
Since you need both sets of contacts for each user to pass to new User() use one map() that returns a $.when() for both contacts requests. Create the user in then() of that $.when()
Something like:
self.getAll = function(callback) {
var users = [];
// return this promise ..... see notes below
return $.getJSON("/API/Users").then(results) {
// map array of promises to pass to final $.when
var promises = $.map(results, function(item) {
var req1 = $.getJSON("/API/Users/contacts/" + item.id);
var req2 = $.getJSON("/API/Users/contacts2/" + item.id);
// return this promise to mapped array
return $.when(req1, req2).then(function(contacts1, contacts2) {
// create user now that we have both sets of contacts
users.push(new User(item, contacts1, contacts2));
});
})
// should return this promise .... see notes below
return $.when.apply($, promises).then(function() {
callback(users);
// return `users` ...see notes below
});
})
}
Using a callback is an outdated approach when you could just return the promise chain shown in comments above and do :
self.getAll().then(function(users) {
// do something with users
})

Javascript promise wait for AccessToken value

I got huge problem with understanding values i got function which getting array with access token and I passing this token to ajax url to get json data. I know I need to use there promise to run ajax after I get access token. Could you help me with this one ?
componentDidMount: function () {
var component = this;
var accessToken = getAccessToken();
$.ajax({
type: 'GET',
url: window.APIUrl +'services/?access_token=' + accessToken,
dataType: 'json',
success: function(response)
{
component.setState({
services : response
});
}
});
}
function getAccessToken(){
var client_id = '****',
client_key = '****',
$ = jQuery;
if(!window.accessToken){
$.ajax({
url : APIUrl + 'auth',
method : 'post',
data : {
'id' : client_id,
'key' : client_key
},
success: function(response){
if(typeof response.access_token != 'undefined'){
/*console.log(response);*/
window.accessToken = response.access_token;
return response.access_token;
}else{
return false;
}
}
});
}else{
return window.accessToken;
}
}
Make your function getAccessToken to return a promise
componentDidMount: function () {
var component = this;
getAccessToken()
.then(function(accessToken) {
var url = window.APIUrl +'services/?access_token=' + accessToken,
return $.getJSON(url)
})
.then(function(response) {
component.setState({
services: response
});
});
}
function getAccessToken(){
if(window.accessToken) {
return $.when(window.accessToken)
}
return $.ajax(...) // get access token from server
}
Try something like this
componentDidMount: function () {
var component = this;
getAccessToken().then(function(accessToken) {
$.ajax({
type: 'GET',
url: window.APIUrl +'services/?access_token=' + accessToken,
dataType: 'json',
success: function(response)
{
component.setState({ services : response });
}
});
})
}
function getAccessToken(){
var deferred = $.Deferred()
var client_id = '****',
client_key = '****',
$ = jQuery;
if(!window.accessToken){
$.ajax({
url : APIUrl + 'auth',
method : 'post',
data : {
'id' : client_id,
'key' : client_key
},
success: function(response){
if(typeof response.access_token != 'undefined'){
/*console.log(response);*/
window.accessToken = response.access_token;
deferred.resolve(window.accessToken)
} else {
deferred.reject()
}
}
});
} else {
deferred.resolve(window.accessToken)
}
return deferred.promise()
}

Know if operation succeeded or rejected with promises

I have a main function where I want to check if a record exists or not in order to create or update the record, so in this function I am calling a helper function that checks for that record using ajax call, and then I want a true/false to be returned to the main function, but do I return defrred.resolve() and deferred.reject(), and how do I check on them? I can't seem to be able to implement it in promises.
Here's my code below, any hint is appreciated.
function _mainFunction()(
var recordID = prompt("Enter Desired Record ID");
var promise = _helperFunction(recordID);
promise.then(...) //do some processing when the reocrd is created or updated
)
function _helperFunction(passedId){
if (passedId) {
if (!_isRecordExists(passedId)) {
// if record doesn't exist, create it.
}
}
}
function _isRecordExists(passedId){
var decision;
var baseUrl = "some url";
var dfd = $.ajax({
url: baseUrl,
type: "GET",
contentType: "application/json;odata=verbose",
headers: {
"accept": "application/json;odata=verbose"
}
});
dfd.promise().then(
function(data, status, jqXHR){
decision = true;
dfd.resolve();
},
function (jqXHR, status, error) {
decision = false;
dfd.reject();
});
return decision; // do I return decision here for true or false?
}
}
You need to return promise object from _isRecordExists function. Then in _helperFunction if-block wouldbe transformed into success/error callbacks of the promise returned from the previous check:
function _mainFunction() {
var recordID = prompt("Enter Desired Record ID");
var promise = _helperFunction(recordID);
promise.then(function() {
console.log('Do something else');
}, function() {
console.log('Failed to find and create new. Maybe try again');
});
}
function _helperFunction(passedId) {
return $.Deferred(function(deferred) {
if (passedId) {
_isRecordExists(passedId).then(function(recordObj) {
// record exists, do something with it
console.log('Exists');
deferred.resolve(recordObj);
}, function() {
// record doesn't exist, create it.
console.log('Does not exist');
deferred.reject();
});
}
deferred.reject();
}).promise();
}
function _isRecordExists(passedId) {
var decision;
var baseUrl = "some url";
return $.ajax({
url: baseUrl,
type: "GET",
contentType: "application/json;odata=verbose",
headers: {
"accept": "application/json;odata=verbose"
}
});
}
Here is also a rewritten _helperFunction implemented with a real promises (either with a polyfill or native):
function _helperFunction(passedId) {
if (passedId) {
return Promise.resolve(_isRecordExists(passedId)).then(function(recordObj) {
// record exists, do something with it and pass further
return recordObj;
}, function() {
// record doesn't exist, create it
return createNewRecord(); // createNewRecord should return new promise
});
}
return Promise.reject();
}
function _mainFunction(){
var recordID = prompt("Enter Desired Record ID");
_helperFunction(recordID)
.then(function(decision) {
// you can use decision here
})
.catch(function(decision) {
// passing decision as true or false in _isRecordExists fn, just for information
// or future usages
// then / catch status already gives the idea
});
}
function _helperFunction(passedId){
var deferred = $.deferred();
if (passedId) {
_isRecordExists(passedId))
.then(function(data) {
// then means exists : do whatever you want here
// if you want to return the result as promise;
deferred.resolve(data);
})
.catch(function(errorData) {
// catch means does not exist : create or do anything
deferred.reject(errorData);
});
} else {
// no id provided
deferred.reject();
}
return deferred.promise();
}
function _isRecordExists(passedId){
var decision;
var baseUrl = "some url";
var dfd = $.ajax({
url: baseUrl,
type: "GET",
contentType: "application/json;odata=verbose",
headers: {
"accept": "application/json;odata=verbose"
}
});
return dfd.promise().then(
function(data, status, jqXHR){
decision = true;
dfd.resolve(decision);
},
function (jqXHR, status, error) {
decision = false;
dfd.reject(decision);
});
}
}
Syntax errors at function _mainFunction()( , close of _mainFunction() at ) ; jQuery promise object not returned from _helperFunction
function _mainFunction() {
var recordID = prompt("Enter Desired Record ID");
var promise = _helperFunction(recordID);
promise.then(function success(t) {
// resolved
console.log(t)
}, function err(e) {
// rejected
console.log(e)
})
//do some processing when the reocrd is created or updated
}
function _helperFunction(passedId) {
if (passedId) {
// return `_isRecordsExists`
return _isRecordExists(passedId)
.then(function(data) {
return data
}, function err(data) {
return data
})
} else {
// if `passedId` not entered, return rejected deferred
return $.Deferred().reject("no passedID")
}
}
function _isRecordExists(passedId) {
var decision;
var baseUrl = "some url";
// do asynchronous stuff
// var dfd = $.ajax({
// url: baseUrl,
// type: "GET",
// contentType: "application/json;odata=verbose",
// headers: {
// "accept": "application/json;odata=verbose"
// }
// });
var dfd = $.Deferred(function(d) {
setTimeout(function() {
d.resolve()
}, Math.random() * 2000)
});
// return `dfd` promise here
return dfd.promise().then(
function(data, status, jqXHR) {
decision = true;
return decision
},
function(jqXHR, status, error) {
decision = false;
return decision
})
// return dfd.promise();
// do I return decision here for true or false?
}
_mainFunction()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
function _mainFunction() {
var recordID = prompt("Enter Desired Record ID");
var promise = _helperFunction(recordID);
promise.then(...) //do some processing when the reocrd is created or updated
}
function _helperFunction(passedId){
if (passedId) {
if (!_isRecordExists(passedId)) {
// if record doesn't exist, create it.
}
}
}
function _isRecordExists(passedId){
var decision;
var baseUrl = "some url";
var dfd = $.ajax({
url: baseUrl,
type: "GET",
contentType: "application/json;odata=verbose",
headers: {
"accept": "application/json;odata=verbose"
}
});
dfd.promise().then(
function(data, status, jqXHR){
decision = true;
dfd.resolve();
},
function (jqXHR, status, error) {
decision = false;
dfd.reject();
});
return decision;
// do I return decision here for true or false?
// answer: NO!!, before the value(true or false) is assigned to decision, decision is returned...(Of course, the value may be allocated and then return). The Promise object should return to the place where the actual value is used.
}
}
// here is my answer
function _mainFunction(passedId){
var recordID = prompt("Enter Desired Record ID");
isExistPromise = _isRecordExists(recordID);
isExistPromise.then(function(data){
if (data.isExist) {}
else {}
});
}
function _isRecordExists(passedId){
var decision;
var baseUrl = "some url" + passedId;
return $.ajax({
url: baseUrl,
type: "GET",
contentType: "application/json;odata=verbose",
headers: {
"accept": "application/json;odata=verbose"
}
});
}
then I want a true/false to be returned to the main function
You can't return true/false to the main function because by the time your code finish execute, the promise is still working and does not have a result yet, hence your _mainFunction does not know if it should return true or false.
What you can do is return a Promise in _mainFunction and then use .then or .fail to do your logic code.
function _mainFunction()(
var recordID = prompt("Enter Desired Record ID");
var promise = _helperFunction(recordID);
promise.then(function (result) {
if (result == true) {
// Do something
} else {
// Do something else
}
})
)
function _helperFunction() {
return $.ajax(...)
.then(function (response) {
if (...) {
return true;
} else {
return false;
}
});
}
From what I observe in your code, I think you should really spend sometime on learning how to work on asynchronous programming in JavaScript.
These are the helpful links that you might want to read:
Asynchronous JavaScript Programming
An introduction to jQuery Deferred / Promise and the design pattern in general

Categories