SAPUI5 / OpenUI5:onInit函数中的attachRequestCompleted模型

时间:2016-02-04 13:22:31

标签: sapui5

我的 Component.js 中定义了两个模型。一个是所有联系人的列表,另一个是登录的联系人。现在我想检查我的控制器是否登录的联系人已经存在于所有联系人列表中。我再次从列表中比较登录联系人的令牌中的registrationToken。但是当我遍历列表时,由于异步通信,长度为0。 我看到了 attachRequestCompleted 函数,但现在我又遇到了另一个问题......当我的attach-function填满我的视图时,onInit函数已经完成 - 模型..

onInit : function(){
    var gLocalContact = sap.ui.getCore().getModel("gLocalContact");
    var gRemoteContacts = sap.ui.getCore().getModel("gRemoteContacts");

    gRemoteContacts.attachRequestCompleted( function() {
        ... if ... setProperty to gLocalContact.getProperty("/registrationToken")...
        console.log("I should be the first log to get the data in view");
    });

    console.log("I should be the second log!");
    this.getView().setModel(gLocalContact, "localContact");
}

attach-function中的第一个日志应该是第一个因为我在我的视图中定义了一些数据到 gLocalContact 。另一个问题是我无法访问我的gLocalContact变量....

1 个答案:

答案 0 :(得分:2)

这有点难看,因为SAPUI5不支持promises。因此,在您的视图中,您不知道是否会触发requestCompleted事件或者是否已加载数据。我想到了一些解决方案:

  1. 在调用loadData()之前,在您的组件中附加requestCompleted事件处理程序。那么你可以保证你会得到这个活动。 您必须构建视图以处理空的gLocalContact模型。但只要模型填充了数据,绑定就会更新视图。

  2. 将onInit()的剩余内容放入事件处理程序中。为了确保获取事件,请检查模型中是否已有数据,如果是,请手动调用您的事件处理程序以使其至少运行一次。

  3. 使用jQuerys Promises进行同步。这样您也可以等待第二个模型:

  4. onInit : function(){
      var gLocalContact = sap.ui.getCore().getModel("gLocalContact");
      var gRemoteContacts = sap.ui.getCore().getModel("gRemoteContacts");
    
      console.log("Wait some seconds for the data...");
      var localContactPromise = this.getPromise(gLocalContact, "/origin");
      localContactPromise.done(function() {
        //same code as before but this time you can be shure its called.
        //... if ... setProperty to
        //gLocalContact.getProperty("/registrationToken")...
        console.log("I should be the first log to get the data in view");
      });
    
      var remoteContactsPromise = this.getPromise(gRemoteContacts,"/origin"); //Wait for the other model to
      $.when(localContactPromise, remoteContactsPromise).done(function(){ 
        //When both models are loaded do this
        console.log("I should be the second log!");
        this.getView().setModel(gLocalContact, "localContact");
        this.byId("label").setText("all loaded");
      }.bind(this));
    },
    getPromise:function(oModel, pathToTestForData){
      var deferred = $.Deferred();
      if (oModel.getProperty(pathToTestForData))
        deferred.resolve(); //Data already loaded
      else
        oModel.attachRequestCompleted(deferred.resolve); //Waiting for the event
    
      return deferred.promise();
    }
    

    完整example on JSBin

    Promise是具有完成事件的对象。 Deferred是一个具有Promiseresolve()方法的对象,该方法将在该Promise上引发done事件。如果您首先在Deferred上调用resolve(),然后为done注册一个处理程序,则会立即调用该处理程序。因此,即使您比异步加载请求慢,也不会错过该事件。

    但是:如果在视图初始化时甚至无法在组件/核心上设置模型,则会出现严重问题,因为没有modelChanged事件。我建议创建一个空模型并将其分配给组件init-method中的组件,然后在该模型上使用loadData()