oDataModel.read() variable visibility : SAPUI5 [duplicate] - javascript

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 2 years ago.
I have one oDataModel and I am reading a particular property, with read function. When data read is success I am assigning it to a variable. But it is always saying undefined
readData : function(){
var oModel = this.getView().getModel();
var locationID;
oModel.read('/Locations',{
success: function(oData,oResponse){
console.log(oData.results[0].id); //This is printing the data in console, properly
locationID = oData.results[0].id;
}
});
console.log(locationID); //This is printing as undefined
}

read is asynchronous. When you do oModel.read, it essentially fires the request but doesn't block the executing thread. If you do a debug of the above code, you'll observe that execution goes to console.log(locationID); immediately after oModel.read. At this point, locationID is undefined (Since assignment hasn't happened yet). The assignment only happens after the callback function success is executed.
To solve this, you can wrap your oModel.read within a Promise. You need to resolve your promise inside success.
readData: function() {
var oModel = this.getView().getModel();
var locationID;
new Promise((resolve, reject) => {
oModel.read('/Locations', {
success: function (oData, oResponse) {
console.log(oData.results[0].id);
locationID = oData.results[0].id;
resolve(locationID)
},
failure: function (oError) {
reject(oError)
}
});
}).then(data => console.log(data))
}
I'm not 100% sure of the syntax, but this should help put you on the right path.

Related

Code execution does not wait for value returned [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
I have following controller and code execution does not wait for the function to bring back values. So some lines of code fail as they are still undefined. How to make sure line execution is in sync.
Also Note: caller function is inside a for loop.
A Controller.js
for (var i=0; i< parseObj.length; i++){
callerFunc: function() {
vc._getValues(A, B, C).then(function (data) {
var vendorNo = data.vendorNo;
var vendorName = data.vendorName
});
// lines of code
}
_getValues: function(A, B, C){
var filters = [
.....
];
var vc = this;
return new Promise(function (resolve, reject) {
service.getDataByFilters(vc, filters,
function (data) {
resolve(data);
},
function (error) {
reject();
}
);
});
the problem is that you need to wait for the result. Service.getMaterial is returning a Promise so when you try to execute the line of code var x = data.Vendor; the variable data is not yet defined.
What you can do is to just call a function inside the promise result (the then function).
I would suggest you learn a little bit more about:
Promise
async/await pattern
I also would like you to know that promise/async-await are not supported by IE in general if I'm not wrong ;)

NodeJS require scope variables [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
I have a module like this.
somemodule.js
module.exports = {
val: null,
get: function() {
finddata('/', function(resp) {
this.val = resp
}
}
}
and is called like this:
var x = require('somemodule');
x.get();
x.get();
After the 1st get call, this x.val is not being set. Tried this as well which does not work:
module.exports = {
val: null,
get: function() {
var that = this;
finddata('/', function(resp) {
that.val = resp
}
}
}
How do I set x.val?
Your finddata is running asynchronously , it's getting called and returned back immediately to continue next line execution . That moment its not sure callback is executed or not . Once callback is executed then only value will be set . To make sure value is set and then after getting the value , you can use promises.
I have just taken two sample file a.js and b.js to explain how it works
a.js
module.exports = {
val:null,
get:function(){
var that = this;
return new Promise(function(resolve, reject) {
that.finddata('/', function(resp){
that.val = resp;
resolve()
})
});
},
finddata :function(path,callback){
setTimeout(function() {
console.log("Lets wait for some time");
callback(10);
}, 100)
}
}
b.js
var x = require('./a');
x.get().then(function(){
console.log(x.val)
});
Output
Lets wait for some time
10
First of all, problem is not about requiring something and it is not related to scope. What is actually happening is, as already stated by others, finddata is asynchronous function meaning that you don't know at what time in future callback function (resp) {...} will be invoked and when val be something other than null. To tackle this you need either to pass additional callback to get function, or to return a promise from get function. Cleaner approach would be to return Promise from get function.
x.get()
.then(() => {
// val is ready
})
or
x.get(() => {
// val is ready
})
Another problem that you have is that you are not taking into account what if finddata invokes your callback with an error? Having something like:
finddata('/', function(resp){
that.val = resp
}
Is really something what you don't want to have. With code that you have, if finddata invokes your callback with an error, val would be equal to that error, otherwise it would be equal to null, if finddata complies to node best practices to invoke callback with null if there was no errors, such as cb(null, data).
Besides that what you are trying to do? Is there a need for exposing module with val thing? Is get function meant to be called regularly from app? If so why introducing new module, just call finddata which is i guess module by itself already.

Return data from an AJAX request [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
I have json data in file that I want to read. It prints to the console.log the correct file data.
How do I get that data into variable x? When I run the code, x is undefined.
function getData() {
$.get('data/APPFeaturesMetaData.json', function (data) {
console.log(data);
return data;
});
};
var x = getData();
It's an asynchronous call, So the var x = getData(); runs before the AJAX request is complete.
The answer is, use deferred it looks something like this:
var request = $.ajax(
{
url: url,
});
// When the request is done, do something with data.
request.done(function (data) {
console.log(data);
});
In your case, it's different if you want to return data, you will have some scoping problems. the fix is really easy, Here's what your final code will look like, I will explain stuff in the comments:
function getData() {
// This is where we store the data.
var myData;
// This will refference current object.
// You need to keep the refference of this object.
var self = this;
$.get( 'data/APPFeaturesMetaData.json' ).done(function(data) {
// the keyword `this` will not work here, because you're inside an AJAX callback.
// When you say `this`, you're actually refferencing the AJAX object
// And not the getData object.
self.myData = data;
});
return myData;
};

JavaScript/JQuery: Correct passing of local variables from a loop to anonymous ajax callback function? [duplicate]

This question already has answers here:
Javascript infamous Loop issue? [duplicate]
(5 answers)
Closed 8 years ago.
Hello there I have the following problem - within a loop I have a certain number of jQuery ajax calls - in the return of the ajax call I want to use a local variable as well as the data returned by the ajax call:
In the JavaScript class DOCache.class.js (note that I use the global variable doCache here, which also does not "feel clean" but I do not know how to pass "this"):
function DOCache() {
this.cache = new Array();
this.capi = new JsonAPI();
// loads all the properties saved in the cache object
this.loadUpdateCache = function(allLoaded) {
for(var prop in this.cache) {
// a delay will be here for each object!
this.capi.get(this.cache[prop]['url'],(function(data) {
doCache.cache[prop]['data'] = data;
doCache.cache[prop]['ready'] = true;
if(doCache.cache[prop]['loaded'] instanceof Function) {
var propLoaded = doCache.cache[prop]['loaded'];
propLoaded(data);
}
// check all initialized
if(doCache.checkAllReady()===true && allLoaded instanceof Function) {
allLoaded(doCache.cache);
}
}) (prop) // KEY: If we have this, we get the correct prop - if removed, we get the correct data - but never both
);
}
};
}
In JsonAPI.class.js:
function JsonAPI(){
this.ajax = function(request_method,api_url,data,done,fail,always) {
var jqxhr = $.ajax(
{
type:request_method,
dataType: "json",
url: JSON_BASE+api_url,
data: data
},JSON_BASE+api_url,data)
.done(function(data) {
if(done instanceof Function) {
done(data);
}
})
.fail(function(data) {
if(fail instanceof Function) {
fail(data);
}
})
.always(function(data) {
if(always instanceof Function) {
always(data);
}
});
return jqxhr;
};
this.get = function(api_url,done,fail,always) {
return this.ajax('GET',api_url,"",done,fail,always);
};
}
The problem is that I do not know how to pass the local variable from the loop (which is a different string on each loop iteration) to the actual callback function without passing it explicitly using (prop) . But if I do this I do not get the data from the callback passed in.
So the actual question is: How can I use a local variable from an iteration (which obviously end before any ajax response is returned) in an Ajax callback function?
Try to aggregate your Ajax calls within an array. Then use $.when to set the callback:
var ajaxRequests = [];
var req1 = $.ajax();
ajaxRequests.push(req1);
$.when(ajaxRequests).done(function () {});
Note, this code is untested.

Scope of Javascript Variable [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
return from a function ajax
JavaScript asynchronous return value / assignment with jQuery
How do you output the data variable to the second alert statement.
$.post("index.ajax.php", { lookup:value },
function(data) {
alert(data)
test = data;
})
alert(test)
Or would it be possible to do something like this?
function confirm_search(input) {
$.post("index.ajax.php", { lookup:input },
function(data) {
$("#temp").val(data);
})
}
var test = confirm_search(value);
alert(test);
You can't.
AJAX is asynchronous. The response is not available until some time later.
The jQuery.post call will begin the AJAX request, and return the jqXHR object which is handling the request. The script will continue to be executed (alert(test) will fire next), and then some time later when the AJAX request has completed (i.e. the HTTP response is received), the callback:
function(data) {
alert(data)
test = data;
}
will be executed.
If you are strict with scenerio, define test variable in global scope, in that way you can use it anywhere in your code.
Try this way :
var test;
$.post("index.ajax.php", { lookup:value },
function(data) {
alert(data)
test = data;
})
function alertTest(){
if(test != undefined) {
alert(test);
clearInterval(t);
}
}
var t = setInterval(alertTest, 1000);
You will get test value when ajax request is completed and test is assigned

Categories

Resources