How to handle callback of fetch

1
Currently, I have the following code in my widget:   var splitArray = this.messageAttribute.split("/"); var path = splitArray[0]; var entity = splitArray[1]; var attr = splitArray[2]; this._contextObj.fetch(this._contextObj.getEntity() + "/" + path + "/" + entity, function(obj) { var message = obj.get(attr); }); However, this is not working: obj exists and has the expected values, but attr is undefined in the callback (it is defined before the callback, and has the expected value). I have tried to pass attr as a second attribute in the function (so: function(obj, attr)), but that doesn't work either. Furthermore, in the callback, 'this' is undefined as well. How do I properly handle the result of a fetch call in its callback? Let's assume I want to set this.property to obj.attr.
asked
2 answers
-1

The reason that "this" is undefined is because you're in a different context. One trick for the "this" is often:

var self = this;
this.something(function(obj){
  console.log(self.something);
});

So in that respect it's odd that "attr" is not working now. 

Edit:
As Jelte pointed out, dojo Hitch is prefered over "var self/_this = this" constructs, so an updated code example here of what should work: 

Make sure dojo lang is included in your widget (it comes with the AppStoreWidgetBoilerPlate):

define([
  "...",
  "dojo/_base/lang",
  "...",

], function(..., dojoLang, ...) {

 

//Fetching function
_fetchingFunction: function() {
  this._contextObj.fetch(..., dojoLang.hitch(this, this._functionToExecuteAfterFetch));
},

//Function to execute when fetched
_functionToExecuteAfterFetch: function(obj) {
  var 
    attr = this.getFromSomewhere,
    message = obj.get(attr);
},

 

Or if you don't want the two functions separately:

//Fetching function
_fetchingFunction: function() {
  this._contextObj.fetch(..., dojoLang.hitch(this, function(obj){
    var 
      attr = this.getFromSomewhere,
      message = obj.get(attr);
  });
}

 

answered
2

JavaScript is function scoped. This means that a function can only see the variables declared in that same function or any scoped above it. Normally in a widget, you don't really notice this because you call the functions directly, keeping you in this same scope.

In this case, the fetch function does an async request to the server. Once the server responds, a new javascript scope is started 'out of thin air' to process the new data. This is then passed on to the function you provided. Seeing as this function was newly created, it doesn't have any of the variables you would normally have within your widget's scope.

The best way to fix this is to use dojo hitch. This is used in practically all of the Mendix custom widgets. You give it your 'this' and a function (the one you already have there) and whenever it gets called, the hitch function makes sure it is executed in that same scope using some JavaScipt magic (google for 'Javascript call and apply functions' if you're curious).

Edit:

Try this one as an example:

Format String

Make sure you add "dojo/_base/lang" as a dependency under for example 'lang' and then use lang.hitch(this, function (data) { <your code>});

answered