Using 'this' inside of an observer callback [duplicate] - javascript

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);
}
});

Related

How do I access a constructor "this" variable? [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 1 year ago.
In my updateCamera(event) function, I am trying to access this.camera as can be shown in my constructor. Unfortunately, it's undefined in that function, I assume it's a scope issue, but I'm not sure how to solve it. Any ideas? Thank you.
export default class Experience {
constructor(options = {}) {
this.camera = new Camera();
// removed unnecessary stuff
this.onMouseDrag();
}
updateCamera(event) {
console.log(this.camera); //Prints "undefined" in the console
this.camera.position.x = (event.clientX / window.innerWidth) * 2 - 1;
}
onMouseDrag() {
window.addEventListener("mousedown", () => {
window.addEventListener("mousemove", this.updateCamera);
});
window.addEventListener("mouseup", () => {
window.removeEventListener("mousemove", this.updateCamera);
});
}
this behaves confusingly in class components.
When binding to a method (your event listener), this is not bound by default. To fix your issue, change this.updateCamera to this.updateCamera.bind(this) or use an anonymous function (()=>this.updateCamera()).
You can also bind this to your functions in your constructor to reduce confusion like this:
this.updateCamera = this.updateCamera.bind(this);

How do i delete a function in javascript [duplicate]

This question already has answers here:
stop settimeout in recursive function
(7 answers)
Javascript delete a function
(3 answers)
Closed 2 years ago.
const resumeInfinity = () => {
window.speechSynthesis.resume();
const timeoutResumeInfinity = setTimeout(resumeInfinity, 1000);
console.log(timeoutResumeInfinity);
}
utterThis.onstart = () => {
resumeInfinity();
};
need the (resumeInfinity) function to stop working after the speechSynthesi
To avoid error messages that resumeInfinity is not a function you shouldn't delete it but set it to an empty function. But as you set defined resumeInfinity as const you can't change that function.
So what you can do is to either change it to:
let resumeInfinity = () => {
// ... your code
}
And then do change it later to an empty function resumeInfinity = () => {}
But you need to keep in mind that if that original function was passed as callback earlier to somewhere else (e.g. like here setTimeout(resumeInfinity, 1000)) that this callback will still refer to the old function.
So a better solution would be to check if the function should still valid to be executed and do an early out otherwise.
const resumeInfinity = () => {
if( /* some check if isn't valid to call that function anymore */ ) {
return
}
window.speechSynthesis.resume();
const timeoutResumeInfinity = setTimeout(resumeInfinity, 1000);
console.log(timeoutResumeInfinity);
}
But all of these above solutions are in fact just a workaround, because if the logic of your application is correct then such a situation should never happen. So the need to do something like this indicates that you more likely need to think about restructuring your code.
If it is just about stopping the timeout then you need to call clearTimeout(timeoutResumeInfinity), and make timeoutResumeInfinity available at the place at which you know that the speechSynthesi finished.

Access THIS inside Jquery listener [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 4 years ago.
I'm trying to achieve the task shown by the example code below, but get this error :
Uncaught TypeError: this.myFunction is not a function
I know i'm doing something wrong but don't know the right way to do it : how can i access the 'this' object inside a Jquery listener ?
Thanks in advance !
var MyClass = function () {
return {
myFunction: function () {
console.log('Do something');
},
myOtherFunction: function() {
$('#myButton').on('click', function () {
this.myFunction(); // here i get the error
});
}
}
}
You can use arrow function, it takes care of auto binding and you can stay away with scope related issues
ES6:
var MyClass = () => {
return {
myFunction: () => {
console.log('Do something');
},
myOtherFunction: () => {
$('#myButton').on('click', () => {
this.myFunction(); // this will be available here
});
}
}
}

Using this in promise scope with babel [duplicate]

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()) {

Javascript - referring to "this" in function run upon click [duplicate]

This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 7 years ago.
I have a method of an object that is called upon click, and the this unfortunately refers to the window object instead of the object that I want it to be referring to.
I've read a several posts that mention this issue, but I have not found/understood any alternatives for my situation.
Any assistance in which direction to go would be appreciated
JSFIDDLE
var IceCream = function(flavor) {
this.tub = 100;
this.flavor = flavor;
};
IceCream.prototype = {
scoop: function() {
this.updateInventory();
alert("scooping");
},
updateInventory: function() {
this.tub--;
alert(this.tub);
}
};
var vanilla = new IceCream("vanilla");
vanilla.scoop();
$('button').click(vanilla.scoop);
$('button').click(function(){
vanilla.scoop();
});
Change the last line to this should make it work. The $.fn.click function takes a callback, with event as the first argument, and binds the element as this, not window.
------------Edit------------
To make this a little bit cleaner, you can define a function to return a click function. Define your class like so:
IceCream.prototype = {
scoop: function() {
this.updateInventory();
alert("scooping");
},
updateInventory: function() {
this.tub--;
alert(this.tub);
},
makeClickFn: function(){
var self = this;
return function(event){
self.scoop();
};
}
};
And when you need to bind the click function:
$('button').click(vanilla.makeClickFn());
jsfiddle: https://jsfiddle.net/L7e71sLL/
$('button').click(vanilla.scoop.bind(vanilla));
Bind, creates a function whose this variable is bound to the given object. In this case vanilla
Inside $('button').click() the scope will be of the button. So you need to bind the vanilla scope to the onClick function

Categories