2015-08-26 6 views
7

Ich habe Probleme, herauszufinden, wie dies zu tun ist (wenn es überhaupt möglich ist).ExtJS: Verwenden von remote geladenen Singleton-Werten für die Filialdefinition

Ich habe eine App, die parse.com verwendet, um ihre Daten zu speichern, die Sache ist, ich will, dass jeder Benutzer ein anderes parse.com-Konto hat, so dass ihre Datensätze sich überhaupt nicht überschneiden. Also habe ich einen Singleton (Einstellungen) erstellt, der die appId und apiKey des Benutzers speichert, die von einem allgemeinen parse.com-Account geladen werden, der von mir verwaltet wird und die E-Mail, appId und apiKey jedes Benutzers enthält, wenn sie sich bei der App anmelden die appId und apiKey des Benutzers.

Die Sache ist, dass ich diese Einstellungen, appId und apiKey, in den Definitionen meiner Stores verwenden muss, da ich sie in den Kopfzeilen senden muss. Ich habe einige Tests durchgeführt, bei denen versucht wurde, die Globals meiner Singletons zu setzen, wenn die App startet, aber zum Zeitpunkt der Speicherdefinition sind beide dieser "Globals" null, da die App noch nicht gestartet wurde.

Hier ist etwas von meinem Code, damit ich mich ein wenig klarer machen kann, da ich weiß, dass dies nicht die einfachste Sache zu verstehen ist.

application.js

Ext.define('Settings', { 
    singleton: true,   
    appId: null, 
    apiKey: null 
}); 


Ext.define('MyApp.Application', { 
    extend: 'Ext.app.Application',   
    name: 'MyApp',   
    stores: [], 
    launch: function() { 
     Ext.create('MyApp.store.Settings').load({ 
      params: { 
       'where': '{"email": "[email protected]"}' //email is supposed to be a user input but for the sakes of testing I just made it static 
      }, 
      callback: function(records){ 
       var s = records[0]; 
       Settings.appId = s.get('appId'); 
       Settings.apiKey = s.get('apiKey'); 
       Parse.initialize(Settings.appId, Settings.apiKey); 
      } 
     }); 
    }, 


    onAppUpdate: function() { 
     Ext.Msg.confirm('Application Update', 'This application has an update, reload?', 
      function (choice) { 
       if (choice === 'yes') { 
        window.location.reload(); 
       } 
      } 
     ); 
    } 
}); 

Shop

Ext.define('MyApp.store.Things', { 
    extend: 'Ext.data.Store',   
    model: 'MyApp.model.Thing',   
    proxy: { 
     type: 'rest', 
     api: { 
      read: 'https://api.parse.com/1/classes/Thing', 
      create: 'https://api.parse.com/1/classes/Thing' 
     }, 
     reader: { 
      type: 'json', 
      rootProperty: 'results' 
     }, 
     useDefaultXhrHeader: false, 
     withCredentials: false, 
     headers: { 
      'X-Parse-Application-Id': Settings.appId, //this is null at the time of definition, but I want it to be the newly fetched value at the time of app launch 
      'X-Parse-REST-API-Key': Settings.apiKey, //this is obviously null as well 
      'Content-Type': 'application/json' 
     } 
    }, 
    autoLoad: true, 
    autoSync: true 
}); 

Was ist der Weg, um dieses?

Übrigens, wenn jemand einen richtigen Namen für diesen Thread finden kann, zögern Sie nicht, es zu ändern oder zu empfehlen.

+0

Vielleicht sollten Sie Ihren "Thing" Store erst laden, nachdem Ihre Einstellungen geladen wurden.Setze autoLoad "Thing" store auf false und lade es innerhalb des Callbacks deiner "Einstellungen" Laden laden –

+0

Ich habe das versucht, aber das Problem ist nicht das Laden, sondern die Definition des Ladens. Da diese globalen Variablen beim Laden der Definition null sind, wird der Nullwert verwendet. Das einzige, was einem einfällt, ist das Definieren des Proxy direkt vor dem Laden, aber das Festlegen des Proxys bei jeder Laden des Ladens scheint nicht der richtige Weg dafür zu sein. – lascort

+0

@lascort welche Version von ExtJs benutzt du? – Tarabass

Antwort

1

Versuchen Sie so etwas wie:

Ext.define('Settings', { 
    singleton: true, 
    appId: null, 
    apiKey: null 
}); 

Ext.define('MyApp.store.Things', { 
    extend: 'Ext.data.Store', 

    model: 'MyApp.model.Thing', 

    proxy: { 
     type: 'rest', 
     api: { 
      read: 'https://api.parse.com/1/classes/Thing', 
      create: 'https://api.parse.com/1/classes/Thing' 
     }, 
     reader: { 
      type: 'json', 
      rootProperty: 'results' 
     }, 
     useDefaultXhrHeader: false, 
     withCredentials: false, 
    }, 
    //autoLoad: true, 
    autoSync: true 
}); 

Ext.define('MyApp.Application', { 
    extend: 'Ext.app.Application', 

    name: 'MyApp', 


    stores: ['Things'], 
    launch: function() { 
     var settings = Ext.create('MyApp.store.Settings'); 
     settings.on('load', function() { 
      var things = Ext.getStore('Things'); 
      things.getProxy().setHeaders({ 
       'X-Parse-Application-Id': Settings.appId, 
       'X-Parse-REST-API-Key': Settings.apiKey, 
       'Content-Type': 'application/json' 
      }); 
      things.load(); 
     }); 

     settings.load({ 
      params: { 
       'where': '{"email": "[email protected]"}' //email is supposed to be a user input but for the sakes of testing I just made it static 
      }, 
      callback: function(records) { 
       var s = records[0]; 
       Settings.appId = s.get('appId'); 
       Settings.apiKey = s.get('apiKey'); 
       Parse.initialize(Settings.appId, Settings.apiKey); 
      } 
     }); 
    }, 


    onAppUpdate: function() { 
     Ext.Msg.confirm('Application Update', 'This application has an update, reload?', 
      function(choice) { 
       if (choice === 'yes') { 
        window.location.reload(); 
       } 
      } 
     ); 
    } 
}); 
+0

versuchte dies, endet das Senden der Anfrage mit Null-Werte für appId und apiKey. – lascort

1

würde ich mit Routen vorschlagen, dies zu tun, da Sie ExtJs verwenden 6. Es ist völlig aus der Box, aber ich, was würde es für Ihre Situation ideal. Auf diese Weise können Sie einfach sicher sein, dass beim Aufruf einer Route und wenn ein Teil Ihrer Anwendung geladen ist, Sie immer einige Überprüfungen durchführen können. Dies kann sehr nützlich sein, um beispielsweise Benutzeranmeldeinformationen zu überprüfen. More information about routes can be found here. Und this is a great post, wenn Sie Benutzersitzungen über Routen behandeln möchten.

Die Singleton:

Ext.define('Settings', { 
    singleton: true,   
    appId: null, 
    apiKey: null 
}); 

Der Basisspeicher:

Ext.define('Base', { 
    extend: 'Ext.data.Store', 
    alias: 'store.base', 
    storeId: 'base', 

    autoLoad: false, 

    proxy: { 
     type: 'rest', 
     useDefaultXhrHeader: false, 
     withCredentials: false 
    }, 

    listeners: { 
     beforeload: function(store, operation, eOpts) { 
      store.getProxy().headers = { 
       'X-Parse-Application-Id': Settings.appId, 
       'X-Parse-REST-API-Key': Settings.apiKey, 
       'Content-Type': 'application/json' 
      } 
     } 
    } 
}); 

Der Things Shop:

Ext.define('MyApp.store.Things', { 
    extend: 'MyApp.store.Base',   
    alias: 'store.things', 
    model: 'MyApp.model.Thing',   

    storeId: 'things', 

    requires: [ 
     'Settings' 
    ], 

    proxy: { 
     api: { 
      read: 'https://api.parse.com/1/classes/Thing', 
      create: 'https://api.parse.com/1/classes/Thing' 
     }, 
     reader: { 
      type: 'json', 
      rootProperty: 'results' 
     } 
    }, 
    autoLoad: false, // --> set to false 
    autoSync: true 
}); 

Ihre MainController:

Ext.define('MyApp.view.main.MainController', { 
    extend : 'Ext.app.ViewController', 

    requires: [ 
     'Settings' 
    ], 

    stores: [ 
     'Things' 
    ], 

    routes : { 
     'user/:id' : { 
      before : 'onBeforeUser', 
      action : 'onUser' 
     } 
    }, 

    onBeforeUser : function(id, action) { 
     Ext.create('MyApp.store.Settings').load({ 
      params: { 
       'where': '{"email": "[email protected]"}' //email is supposed to be a user input but for the sakes of testing I just made it static 
      }, 
      callback: function(records){ 
       var s = records[0]; 
       Settings.appId = s.get('appId'); 
       Settings.apiKey = s.get('apiKey'); 
       Parse.initialize(Settings.appId, Settings.apiKey); 
       action.resume(); 
      } 
     }); 

     // or even better 

     Ext.Ajax.request({ 
      url: 'url/to/the/api', 
      params: { 
       'where': '{"email": "[email protected]"}' //email is supposed to be a user input but for the sakes of testing I just made it static 
      }, 
      success: function(response, opts) { 
       var obj = Ext.decode(response.responseText); 

       Settings.appId = obj.appId; 
       Settings.apiKey = obj.apiKey; 
       Parse.initialize(Settings.appId, Settings.apiKey); 
       action.resume(); 
      }, 
      failure: function(response, opts) { 
       action.stop(true); 
      } 
     }); 
    }, 

    onUser : function(id) { 
     Ext.getStore('things').load(); 
    } 
}); 
+0

interessant .. Ich werde dies versuchen und kommen zu Ihnen mit den Ergebnissen zurück, aber es sieht vielversprechend aus – lascort

+0

Es scheint perfekt zu passen, was Sie wollen. Aber ich kenne den Rest Ihrer Bewerbung natürlich nicht. Ich hoffe, es hilft .. – Tarabass

+0

Ok, ich habe versucht, dies zu tun, aber habe das gleiche Ergebnis. Die appId- und apiKey-Header waren beim Laden des Stores immer noch null. Ich habe einen Weg gefunden (und ich kann nicht sehen, wie ich es vorher nicht gesehen habe), obwohl ich es als Antwort geschrieben habe – lascort

1

Ich denke, das Problem kann gelöst werden, indem Proxy-Definition zu Konstruktor von "Things" speichern, wie unten angegeben.

Ext.define('MyApp.store.Things', { 
    extend: 'Ext.data.Store', 

    model: 'MyApp.model.Thing', 
    autoLoad: true, 
    autoSync: true, 

    constructor: function(config) { 

     config = Ext.apply({ 
      proxy: { 
       type: 'rest', 
       api: { 
        read: 'https://api.parse.com/1/classes/Thing', 
        create: 'https://api.parse.com/1/classes/Thing' 
       }, 
       reader: { 
        type: 'json', 
        rootProperty: 'results' 
       }, 
       useDefaultXhrHeader: false, 
       withCredentials: false, 
       headers: { 
        'X-Parse-Application-Id': Settings.appId, 
        'X-Parse-REST-API-Key': Settings.appId, 
        'Content-Type': 'application/json' 
       } 
      } 
     }, config); 
     this.callParent([config]); 
    } 
}); 

Wenn Proxy-Definition innerhalb des Konstruktors ist, sind Settings.appId und Settings.apiKey nur zum Zeitpunkt der Instanz Schaffung von ‚MyApp.store.Things‘ aufgelöst.

+1

Sieht gut aus. Der Nachteil ist, dass Sie dies in jedem Geschäft implementieren müssen. – Tarabass

Verwandte Themen