This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 6 years ago.
I've found one issue while using Babel that I have not been able to resolve yet.
The thing is that I'm using promises within a class method and I need to access the this object of the class inside the promise to invoke class functions.
The code is
class SecurityService {
constructor($q) {
this.$q = $q;
}
isAuthenticated() {
return true;
}
requestCurrentUser() {
return this.$q.when({});
}
requireAuthenticatedUser() {
let deferred = this.$q.defer();
this.requestCurrentUser()
.then(
function (user) {
if (this.isAuthenticated()) {
this.$log.debug('Security: Access granted for user.');
return deferred.resolve(user);
}
return deferred.reject();
}
);
}
}
When I invoke requireAuthenticatedUser method it fails while executing this.isAuthenticated() because it is trying to find it in the promise scope.
Babel usually wraps the this variable in a upper scope variable, doing something like:
var _this4 = this;
to allow the use in the child scope, but it have checked that only does this thing when using callbacks, but not promises.
Is there any preset or any other thing that I need to import to make it work?
You can manually assign this to a variable before calling the method (the same way you're assigning $q.defer()).
requireAuthenticatedUser() {
let deferred = this.$q.defer();
var securityservice = this;
this.requestCurrentUser()
.then(
function (user) {
if (securityservice.isAuthenticated()) {
Related
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 1 year ago.
I have an Angular application that I've just updated from v8 to v12.
The way I handled responses to observables is now deprecated, and while I have changed my code, 'this' no longer works inside the callback and I'm wondering what is the best approach to solve this?
This is how I used to handle observables;
this._trialService.currentTrial().subscribe(trial => {
this.trial = trial;
this.loadVisitDetails()
}, error => {
this._alertService.showWarningAlert(error.error.title);
});
I have changed it to this;
this._trialService.currentTrial().subscribe({
next(trial) {
this.trial = trial;
this.loadVisitDetails()
},
error(error) {
this._alertService.showWarningAlert(error.error.title);
}
});
Because the code no longer uses arrow functions, this no longer refers to the parent class so I am no longer able to access properties and methods on that parent class.
Is there a way to get around this, or will I have to create a variable outside of the callback that will refer to this?
const self = this;
this._trialService.currentTrial().subscribe({
next(trial) {
self.trial = trial;
self.loadVisitDetails()
},
error(error) {
self._alertService.showWarningAlert(error.error.title);
}
});
That just seems a bit messy.
You can still use arrow functions for the handlers:
this._trialService.currentTrial().subscribe({
next: (trial) => {
this.trial = trial;
this.loadVisitDetails()
},
error: (error) => {
this._alertService.showWarningAlert(error.error.title);
}
});
This question already has answers here:
What is 'Currying'?
(23 answers)
Closed 4 years ago.
I recently found JavaScript code like this:
someFunction()()
Function immediately invoked right after function without classic IIFE syntax.
What is that kind of syntax called? And how it works?
Its a function that returns another function.
Here is an example on how it works, this can help you to understand better.
function sum(x){
return function(y){
return x+y;
}
}
sum(3)(5); //8
For you code to work:
someFunction()();
You need to have code that looks like this:
function someFunction() {
console.log('someFunction()');
// do something before return
return function() {
console.log('someFunction()()');
// do something else here
}
}
someFunction()();
In this example you first call someFunction then you call the function that was returned by someFunction.
This can be good to do when you need to pass in a variable that will be used in the inner function but the inner function will be called in the future like this:
function someFunction(outerVal) {
console.log('Outer called.');
return function(innerVal) {
console.log('inner called.');
return outerVal * innerVal;
}
}
var inner = someFunction(12);
setTimeout(()=> {
console.log(inner(4));
}, 1000);
I use this often in Node.js for common middle-ware that needs a single value to be unique.
app.get('/dogs', myFn('woof'));
app.get('/cats', myFn('meow'));
app.get('/birds', myFn('tweet'));
function myFn(word) {
return function(req, res, next) {
res.write(word).end();
}
}
That is an over simplification, but can be vary powerful.
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
How I can return a string from a javascript callback
I have two functions, main function is working on loaded.
and another function is used to calling web service.
I would like to know how can JS return the string value to main function.
thanks
function thisCallJSON(webServiceURL) {
var params = {};
params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.GET;
gadgets.io.makeRequest(webServiceURL, function(response)
{
if(response.data && response.text)
{
var jsondata = response.data;
for (var key in jsondata)
{
var value = jsondata[key];
//alert("Member Name : "+value["memNm"]);
}
}
else
{
//alert("Member Name : Not Found !");
}
}, params);
}; function main(){
var txt_string = "";
txt_string = thisCallJSON("http://192.100.1.59");
}
You can assign the value to the variable in the scope of the main function, but it won't happen before the main function is finished executing because of the event loop. Instead, you should put your code inside the callback, or better yet, look at how you would use javascript promises to accomplish this.
This question already has an answer here:
Promise chaining: Use result from previous promise in next then callback [duplicate]
(1 answer)
Closed 8 years ago.
I'm trying to do a few fetches with Javascript using a Promises API, and then use all of the values I just fetched. Something like...
// Use an Id to find thing 1, use thing 1 Id to find thing2, use thing 2 id to find thing 3,
// then use all of them.
thing1model.findById(thing1id).then(function(thing1) {
return thing2model.findById(thing1.id);
}).then(function(thing2) {
return thing3model.findById(thing2.id);
}).then(function(thing3) {
// Here I want to use all of thing1, thing2, thing3...
someFunction(thing1, thing2, thing3);
}).catch(function(err) {
console.log(err);
});
The problem is thing1 and thing2 go out of scope after the function call. How can I use them in the last then function?
You can save thing1 and thing2 in variables which are declared in scope above your chain.
Like this,
var thing1Data, thing2Data
thing1model.findById(thing1id).then(function(thing1) {
thing1Data = thing1
return thing2model.findById(thing1.id);
}).then(function(thing2) {
thing2Data = thing2
return thing3model.findById(thing2.id);
}).then(function(thing3) {
someFunction(thing1Data, thing2Data, thing3);
}).catch(function(err) {
console.log(err);
});
This question already has answers here:
How do I access previous promise results in a .then() chain?
(17 answers)
Closed 8 years ago.
From what I understand one of the main selling points for Promises is the ability to write flat code (or, flatter than callback hell).
Though it seems that in many cases we need to nest promises, in order to use closure. For example (from q's docs, though I use Bluebird):
function authenticate() {
return getUsername()
.then(function (username) {
return getUser(username);
})
// chained because we will not need the user name in the next event
.then(function (user) {
return getPassword()
// nested because we need both user and password next
.then(function (password) {
if (user.passwordHash !== hash(password)) {
throw new Error("Can't authenticate");
}
});
});
}
Is there a cleaner way to do this, without nesting?
EDIT: I've managed to clean up this specific example using .all, but there are more complex cases where I don't think it can be done:
function authenticate() {
return Promise.all([
getUsername().then(getUser),
getPassword()
]).spread(function (user, password) {
if (user.passwordHash !== hash(password)) {
throw new Error('Can\'t authenticate');
}
});
}
Yes, you can always flatten a promise chain with Promise.all (shorthand through Promise.join in Bluebird) by using promises for the proxies they are. After all - promises abstract values, you can always unwrap a promise as late as you want and have other variables depend on it.
Whether or not it's more readable is another debate:
foo().then(function(a){
return bar(a).then(function(b){
return g(a,b); // "needed" to nest because I wanted `a`
});
});
Can be written as:
var a = foo();
var b = a.then(bar);
Promise.join(a, b, function(a,b){
return g(a, b); // alternatively, res could have been `Promise.join(a,b, g)`
});
So generally - you can always avoid nesting but a lot of time you might not want to.
In your case, this can even be:
function authenticate() {
var userPass = Promise.all([ getUsername().then(getUser), getPassword()]);
var passHash = userPass.get(0).get("passwordHash");
var newHash = userPass.get(1).then(hash);
var equal = Promise.join(userHash, newHash, function(a, b){ return a !==b });
return equal.then(function(val){ if(!val) throw new Error("..."); });
}
Flatter? Sure. Better? That's a whole other question. If you have a nested for loop, you might want to keep it a nested for loop and nest rather than hack around that option and use a single loop.