Because I'm using a prototype that has functions calling other functions in the same prototype I have to refer to that method using this
The Problem this
Created:
But because of that, I have to preserve a context to use this
that has me forming very ugly .bind(this)
walls.
Here is a simplified example I made for laughs.
Killmyself.prototype.fireLeMissles = function () {
return new Promise(function(resolve,reject) {
this.anotherFunction(param).then(function(result) {
someList.forEach(function(item) {
this.fireLeMissles().then(function(anotherResult){
promiseList.push(anotherResult)
})
},this);
Promise.all(promiseList).then(function(promiseItem){
childPlacesIds.forEach(function(childPlaceId) {
//Do Other Stuff
},this);
});
resolve(result);
}.bind(this).catch(function(err){
console.log("Yea, life sucks sometimes.")
}));
}.bind(this));
}
Killmyself.prototype.another = function(){
//Other stuff
}
You can see because of calls to functions in the same prototype such as this.anotherFunction(
... and this.fireLeMissles(
... I had to do deep preservation of context,which now (in my much larger version of this) is making this code hard to work with.
Question:
Is this a "man up and get use to the harder aspects of JavaScript" thing - or do you seasoned developers see simple ways that deep binding like this could have been avoided?
Because I'm using a prototype that has functions calling other functions in the same prototype I have to refer to that method using this
The Problem this
Created:
But because of that, I have to preserve a context to use this
that has me forming very ugly .bind(this)
walls.
Here is a simplified example I made for laughs.
Killmyself.prototype.fireLeMissles = function () {
return new Promise(function(resolve,reject) {
this.anotherFunction(param).then(function(result) {
someList.forEach(function(item) {
this.fireLeMissles().then(function(anotherResult){
promiseList.push(anotherResult)
})
},this);
Promise.all(promiseList).then(function(promiseItem){
childPlacesIds.forEach(function(childPlaceId) {
//Do Other Stuff
},this);
});
resolve(result);
}.bind(this).catch(function(err){
console.log("Yea, life sucks sometimes.")
}));
}.bind(this));
}
Killmyself.prototype.another = function(){
//Other stuff
}
You can see because of calls to functions in the same prototype such as this.anotherFunction(
... and this.fireLeMissles(
... I had to do deep preservation of context,which now (in my much larger version of this) is making this code hard to work with.
Question:
Is this a "man up and get use to the harder aspects of JavaScript" thing - or do you seasoned developers see simple ways that deep binding like this could have been avoided?
Share Improve this question asked Jan 12, 2016 at 4:11 Nick PinedaNick Pineda 6,46211 gold badges50 silver badges69 bronze badges 6 | Show 1 more comment3 Answers
Reset to default 16If you are using ES6, you can benefit from arrow functions, which preserve the context.
var counter = function () {
this.count = 0;
setInterval( () => { // arrow function
console.log(this.count++); // context is preserved
}, 1000)
}
var counter = new counter();
So, your code would become something like:
Killmyself.prototype.fireLeMissles = function() {
return new Promise((resolve, reject) => {
this.anotherFunction(param).then(result => {
someList.forEach(item => {
this.fireLeMissles().then(anotherResult => {
promiseList.push(anotherResult)
});
});
Promise.all(promiseList).then(promiseItem => {
childPlacesIds.forEach(childPlaceId => {
//Do Other Stuff
});
});
resolve(result);
}).catch(err => {
console.log("Yea, life sucks sometimes.")
});
});
}
For ES5, you can either use .bind
exactly the way you did or you can assign this
to something else in the function with the desired context, then use that variable inside the inner functions.
Killmyself.prototype.fireLeMissles = function() {
var self = this; /// use `self` instead of `this` from now on.
return new Promise(function(resolve, reject) {
self.anotherFunction(param).then(function(result) {
someList.forEach(function(item) {
self.fireLeMissles().then(function(anotherResult) {
promiseList.push(anotherResult)
})
});
Promise.all(promiseList).then(function(promiseItem) {
childPlacesIds.forEach(function(childPlaceId) {
//Do Other Stuff
});
});
resolve(result);
}).catch(function(err) {
console.log("Yea, life sucks sometimes.")
});
});
}
for starters I do not understand you you need a new Promise..
here, like @loganfsmyth said, I would simply use arrow functions and reduce the complexity:
Killmyself.prototype.fireLeMissles = function (param) {
return this.anotherFunction(param)
.then(someList => {
var promiseList = someList.map( item => this.fireLeMissles(item));
return Promise.all(promiseList);
}).then(childPlacesIds => {
childPlacesIds.forEach(childPlacesId = {
// .... do something;
});
// return something.
}).catch(err => console.log("Yea, life sucks sometimes."));
}
P. S: I am not sure where this param, someList, childPlacesIds
is coming from, and assumed that you are initializing that promiseList
as empty array.
Mido's answer is good, I just wanted to provide an alternative take on it which I think would be useful to know - using promises for the proxies they are:
Killmyself.prototype.fireLeMissles = function () {
let fn = this.anotherFunction(param);
let others = fn.then(_ => someList.map(this.fireLeMissles, this));
let othersP = Promise.all(others);
othersP.then(/* do OtherStuff */);
return othersP; // or whatever its then returned
}
Of course, this gets even easier with a library like bluebird.
.bnd(this)
ifnesting
is one level up else would go with thevar _this=this
and would have referred_this
inside nested functions.. – Rayon Commented Jan 12, 2016 at 4:17