cancel
Showing results for 
Search instead for 
Did you mean: 

Question regarding closure / scoping in callback functions

frankluzat
Participant
0 Kudos

Hi,

please could anyone explain why the variables sUsername, oModel, sPath, that are not in scope of my callback function for the createBindingContext call? I would expect them to be available as closure variables.

Accepted Solutions (1)

Accepted Solutions (1)

Former Member
0 Kudos

I guess the variables are available and have seen at times the debugger just doesn't pick the variables in the closure when it isn't used ! Try doing this,


function fnSuccess(oContext){

     debugger;

     console.log(oModel);

}

frankluzat
Participant
0 Kudos

Dear Sakthivel,

That was exactly it, thank you!


Chrome devtools can't inspect the closure variables unless they are actually used in the inner function.

Seems to be some kind of optimization the browser does to keep the closure contexts as small as possible.

Answers (1)

Answers (1)

former_member182372
Active Contributor
0 Kudos

try to flip createBindginContext call and function declaration (so it will be first)

frankluzat
Participant
0 Kudos

Already did that. Same result 😞

former_member182372
Active Contributor
0 Kudos

Frank, those variables have values outside the closure? They are visible, value is undefined. Is spath value has a correct username?

former_member182372
Active Contributor
0 Kudos

try to define a variable for function

var fnc = function(){...};

and pass variable to createBindginContext

frankluzat
Participant
0 Kudos

Already tried that too.

The variables are all valid in the scope of the caller of createBindingContext:

The module this userPopover function is declared in is declared this way:


sap.ui.define([ "sap/ui/model/Filter", "sap/ui/model/json/JSONModel", "myapp/util/Formatter" ], function(Filter, JSONModel, Formatter) {

  "use strict";

  return {

 

    // Definitions go here...

  };

});

I wonder why in Chrome Devtool I see sap.ui.define.Formatter.userPopover in the call stack.

Could this have anything to do with this issue?

former_member182372
Active Contributor
0 Kudos

i usually do

jQuery.sap.declare("myapp.util.Formatter");

jQuery.sap.require("sap.ui.model.Filter");

....

myapp.util.Formatter =

{

     userPopover : function(){

     }

}


but honestly i dont really see why that should matter

frankluzat
Participant
0 Kudos

I used to do it that way too, but since the release of 1.30 I switched to the new AMD way of defining my modules because that seems the way to go for the future.

I was only asking because I would have expected to see sap.ui.define.Dialogs.userPopover in the call stack and not sap.ui.define.Formatter.userPopover because my function is in the Dialog.js module.

former_member182372
Active Contributor
0 Kudos

last idea - try to create a local variable with different name

like

var __username = sUsername;

and see if it is visible in scope

frankluzat
Participant
0 Kudos

Tried that and the new variable is not in scope.

I tried something else:

I passed my callback function to createBindingContext because the data will be loaded asynchronously if it is not yet present in the model.

In my case I know that the data has been loaded before so I just tried to call my callback manually and passing the context returned synchronously from createBindingContext:


var oCtx = oModel.createBindingContext(sPath);

  if (oCtx) {

  fnSuccess(oCtx);

  }

In this case all closure variables are visible in my callback function (see above).

So it must have something to do with the callback being called by the library but I don't know what it could be.

Anyway, this was just a try and I don't want to rely on the context being returned synchronously for an application in production.

former_member182372
Active Contributor
0 Kudos

>> I don't want to rely on the context being returned synchronously for an application in production.


didnt really get that point

frankluzat
Participant
0 Kudos

What I wanted to express was that we cannot rely on the return value of createBindingContext because if the entity requested is not yet present in oModel.oData the function returns undefined and triggers the asynchronous loading of the odata entities.

So it is better to use the callback function in any case because this will always receive the context (with data already loaded). Either immediately if the data has been loaded already or asynchronously as soon as the data has been loaded from the server.

frankluzat
Participant
0 Kudos

Maskim, thank you for your help!

Sakthivel solved it (see below).

Regards,

Frank