How to change the context of this inside object - javascript

I want to access a function which is outside my base object, but if we console.log(this) inside loadAll function then it will give the context inside object. If I console.log(this) any normal function i.e without action or getter/setters it will give context of whole class which I want to achieve
base = observable({
isDeleting: false,
registry: observable.map(),
get all() {
return this.registry.values();
},
loadAll:action.bound(function () {
console.log(this);
this.request()
}),
});
request = () => {
console.log('hello');
}
In The above example this will throw an error because it can't access the request function but I wan to find a way to access it.
base = observable({
isDeleting: false,
registry: observable.map(),
get all() {
return this.registry.values();
},
loadAll:action.bound(function () {
console.log(this);
this.request()
}),
request: () => {
console.log(this) //This will give context of all the function outside object that is what I want in above example.
console.log('hello');
},
});

Related

How to call another function inside function in export default?

export default {
one: () => {
//some codes
},
two: () => {
//some codes
one(); // error
this.one(); // error
}
}
I have module like that, and I want to call function one() inside function two().
But I got error like this : TypeError: Cannot read property 'one' of undefined.
How can I fix it? I want to know the cause.
What about extracting them out into separate functions and then include them in the export?
const one = () => {
//some codes
};
const two = () => {
//some codes
one();
};
export default {
one,
two
}
You shouldn´t use arrows function if you want to give a new context to the this keyword.
Look this example, it uses an arrow function in the two method. It would return error since the this keyword is not related to the object, but mantains the context from the last function.
let obj = {
one: function() {
console.log("one");
},
two: () => { // Arrow function
this.one();
}
}
obj.two();
If you use a normal function, the this keyword would be related to the object:
let obj = {
one: function() {
console.log("one");
},
two: function() { // Normal function
this.one();
}
}
obj.two();
This is the main difference between arrow functions and normal functions

How can i pass data from window method to the data function in a Vuejs app

I need to pass data from window method to the data function of a vuejs component
here is my window function
window.authenticate = function(pid, receiptKey) {
console.log("Authentication");
console.log(this)
localStorage.setItem("pid",pid)
alert("pid="+pid+"receipt="+receiptKey)
window.pid=pid
window.receiptKey = receiptKey
}
Data function:
data: () => ({
pid: 0,
receipt: 0
}),
trying to set the Pid and receipt key mounted, where am I wrong ?
mounted: function (){
this.pid = window.pid
alert(this.pid)
this.receipt = window.receiptKey
}
I did some research and found that the created lifecycle hook can be used for this purpose as below
1) we need to bind the window method with component method, window.authenticate to loginCall in the below example, and it all works.
created: function () {
// `this` points to the vm instance
console.log('a is: ' + this.a)
// window.somefunc = this.greet.bind(this);
window.authenticate = this.loginCall.bind(this)
},
methods: {
loginCall: function (pid, receipt) {
}

Vuejs ajax call not mapping changes to underlying html table

I am making simple ajax call with vuejs and axios:
var app1 = new Vue({
el: '#app1',
data: {
test: []
},
methods: {
setAJAX: function () {
axios.get('/Departments/GetDepartments/').then(response => this.test = response.data.listBACAET);
}
}
});
Why is this working:
setAJAX: function () {
axios.get('/Departments/GetDepartments/').then(response => this.test = response.data.listBACAET);
}
But this is not working, changes are not mapped into table (this.test is undefined):
setAJAX: function () {
axios.get('/Departments/GetDepartments/').then(function(response){this.test = response.data.listBACAET});
}
This is because of the way arrow functions work: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_separate_this
When using an arrow function, this is implicitly bound to this of the enclosing scope, which is, in your case, the vue instance on which the method is called.
So you're setting the data of your view model, which works.
When using a std. function, there is no this in the scope, hence the error. To use a std. function, you need to define a closure for your view model like this:
setAJAX: function () {
let vm = this
axios.get('...').then( function(response) {
vm.test = response.data.listBACAET
});
}

expressjs server.js this is undefined, how can I refer to server

In an ExpressJS setup, I have server.js where I do the following:
import { call_method } from '../hereIam.mjs';
const process_db = async () => {
console.log(this); // undefined
call_method(this);
};
console.log(this) // undefined
process_db();
And then, from hereIam.mjs I want to call a parent method, but this is undefined
export const call_method = parent_this => console.log(parent_this); // undefined
I tried to include classes in server.js, in an attempt to force having a this
class AppServer {
constructor() {
console.log(this)
}
const process_db = async () => call_method(this);
}
But it seems that the arrow functions inside classes doesn't compile in (experimental) NodeJS (this should be another question)
EDITED
How I can do this is by avoiding the arrow notation to be able to use classes inside Express, and then instantiate a class that provides a this.
class AppServer {
async process_db() {call_method(this)};
}
let server = new AppServer();
server.process_db();
The question would be, the only way of getting a this reference is by using objects/classes?
You could use the the bind method and pass through any object to be used as the this context.
However, arrow functions receive the context from that which they are called from, function() {} function syntax use the context that was bound to them either implicitly by the context they were defined in or explicitly using this bind method.
So, an alternative to using classes would be to bind a simple object to the method, something like:
const call_method = require('../hereIam.mjs');
const process_db = async function() {
console.log(this);
call_method(this);
};
console.log(this);
const context = {
name: 'bound context',
parent_method: async function() {
console.log('Good evening');
}
}
process_db.bind(context)();
Presuming hereIam.mjs contains:
module.exports = parent_this => console.log(parent_this);
then the script will output:
{}
{ name: 'bound context',
parent_method: [AsyncFunction: parent_method] }
{ name: 'bound context',
parent_method: [AsyncFunction: parent_method] }

Lodash's _.debounce() not working in Vue.js

I am trying to run a method called query() when a component property called q in Vue.js is modified.
This fails because this.query() is undefined. This is referring to my component's instance but somehow does not contain the methods.
Here's the relevant code part where I'm trying to watch the component property q and run the query() function:
methods: {
async query() {
const url = `https://example.com`;
const results = await axios({
url,
method: 'GET',
});
this.results = results.items;
},
debouncedQuery: _.debounce(() => { this.query(); }, 300),
},
watch: {
q() {
this.debouncedQuery();
},
},
Error:
TypeError: _this2.query is not a function
If I write the debounce() call as below, the TypeError: expected a function error appears even earlier, at the page load.
debouncedQuery: _.debounce(this.query, 300),
The issue comes from the lexical scope of the arrow function you define within _.debounce. this is bound to the object you are defining it in, not the instantiated Vue instance.
If you switch out your arrow function for a regular function the scope is bound correctly:
methods: {
// ...
debouncedQuery: _.debounce(function () { this.query(); }, 300)
}
We can do it by plain JS (ES6) with few lines of code:
function update() {
if(typeof window.LIT !== 'undefined') {
clearTimeout(window.LIT);
}
window.LIT = setTimeout(() => {
// do something...
}, 1000);
}
As answered in another post This is undefined in Vue, using debounce method the best way to add debouncing IMO is to create the method normally in methods as eg:
setHover() {
if (this.hoverStatus === 'entered') {
this.hoverStatus = 'active'
}
},
But then replace it in your created block eg:
created() {
this.setHover = debounce(this.setHover, 250)
},

Categories

Resources