0

what is correct way of writing this in js?

notice this.signals.total is in a wrong context.

articleSchema.pre('save', function(next) {
  if (!this.publisher) {
    this.publisher = this.url;
  }

  social.facebook(this.url, function(err, signals) {
   //problem is this
   this.signals.total = signals.total_count;
  });

  if (!this.weight) {
    this.weight = 1440;
  }

  var currentDate = new Date();
  this.updated_at = currentDate;
  if (!this.created_at) {
    this.created_at = currentDate;
  }

  next();
});

this in that case refers to social.facebook correct?

There are several ways I could deal with the problem, e.g. create outside variable, but what is js way?

  • `social.facebook correct?` - nope, depends how calling callback it can be _social_, _window_, or something else, like request or promisse object – Grundy Dec 01 '15 at 08:28
  • @Bergi, i not sure that this duplicate, op not say what _this_ expected – Grundy Dec 01 '15 at 08:40
  • Notice that you probably don't need to assign the result to an outside variable anyway - you cannot use it outside right away, because [it's an asynchronous callback](http://stackoverflow.com/q/23667086/1048572). – Bergi Dec 01 '15 at 08:41
  • 1
    @Grundy: Probably the same `this` as elsewhere in the function. But regardless, the duplicate should show how to bind *any* value to `this`. – Bergi Dec 01 '15 at 08:42
  • @Bergi yes its true, how can I resolve this issue? saving async data? –  Dec 01 '15 at 13:52
  • @salivan: You cannot really, or at least not access the safe before the data appears there. Saving a promise for the data is usually the best approach. – Bergi Dec 01 '15 at 13:57
  • @Bergi so I should read up on promises –  Dec 01 '15 at 13:58
  • Yes, that's never a mistake :-) I can recommend https://github.com/kriskowal/q/wiki/General-Promise-Resources as a good start, although you'll find many more tutorials these days (of varying quality). – Bergi Dec 01 '15 at 14:03

3 Answers3

0

A simple solution is to store a reference to the correct context:

articleSchema.pre('save', function(next) {
  // ...

  var that = this; // Store a reference to `this`.
  social.facebook(this.url, function(err, signals) {
   // Use `that`.
   that.signals.total = signals.total_count;
  });

  // ...
});
Cerbrus
  • 70,800
  • 18
  • 132
  • 147
0

Yes, a common solution is to assign the this pointer to a variable outside the inner function like this:

var self = this;

function foo() {
  // this would not work, but self does
}

In ECMA-Script 6, you can also use an arrow function instead.

social.facebook(this.url, (err, signals) => {
   // this will point to the outer this
});

See this article for more details:

lex82
  • 11,173
  • 2
  • 44
  • 69
0

It is totally depends on how the callback is called.

1/ this will be global.

social.facebook = function(url, fn) {
  fn(url)
}

2/ this will be social

social.facebook = function(url, fn) {
  fn.call(this, url)
}

This way this can also be something weird:

social.facebook = function(url, fn) {
  fn.call(weirdObject, url)
}

Create outside variable like the others answer is one way, the other one is bind.

social.facebook(this.url, function(err, signals) {
  //problem is this
  this.signals.total = signals.total_count;
}.bind(this));
tungd
  • 14,467
  • 5
  • 41
  • 45