2013-05-05 4 views
2

Я хочу подготовить Json Store до обработки до callParent(), затем он выдает сообщение об ошибке.ExtJS 4 - async callback to callParent throws exception

Однако me.callParent() работает нормально снаружи без асинхронного обратного вызова.

Ext.define('My.desktop.AppExt', { 
    extend: 'Ext.ux.desktop.App', 

    someStore: null, 

    init: function() { 
     var me = this; 
     me.someStore = Ext.create('My.store.SomeStore'); 
     me.someStore.load({ 
      scope: this, 
      url: 'some/json/url', 
      callback: function(records, opt, success) { 
       if (success) { 
        me.callParent(); // BOOM! ERROR HERE 
       } 
      } 
     }); 
    } 
}); 

ОШИБКА:

Необработанное исключение в строке 4245, столбец 17 в //localhost/js/ext-all-debug.js

0x800a138f - ошибка JavaScript выполнения:

Не удалось получить свойство «суперкласс» неопределенной или нулевой ссылки

ответ

5

callParent полагается на контекст для вызова правильный метод, так что если вы на самом деле не называть его «напрямую» из метода подкласса, вам необходимо вручную запустить его:

Ext.define('A', { 
    foo: function(){ 
     console.log('foo', 'a');  
    } 
}); 

Ext.define('B', { 
    extend: 'A', 
    bar: function(){ 
     this.self.superclass.foo.call(this);  
    } 
}); 

Ext.onReady(function(){ 
    var o = new B(); 
    o.bar(); 
}); 
+0

Спасибо за быстрый ответ! Интересно, с асинхронными вызовами, кроме callParent() есть ли какие-либо другие функции, которые схожи в той же ситуации, о которой я должен знать? – Tom

+1

'callParent' запрашивает вызывающую функцию, чтобы выяснить, что нужно вызывать. Итак, все, что похоже на «магический» вызов, использует ту же технику. –

0

Один из способов я знаю, чтобы использовать дополнительный параметр, который указывает что родительский метод должен быть вызван:

init: function(callParent) { 
    if (callParent) { 
     this.callParent(); 
    } 
    var me = this; 
    me.someStore = Ext.create('My.store.SomeStore'); 
    me.someStore.load({ 
     scope: this, 
     url: 'some/json/url', 
     callback: function(records, opt, success) { 
      if (success) { 
       this.init(true); 
      } 
     } 
    }); 
} 

Если вы используете this.self.superclass.init.call (это) будет хорошо только до тех пор, пока кто-нибудь будет создавать ребенка для своего класса. this.self.superclass указывает на суперкласс класса , поэтому он будет указывать на My.desktop.AppExt вместо Ext.ux.desktop.App.

Обновлено 24.08.2016: опубликовано более разумное решение (см. Другой ответ от меня).

0

Лучшее решение для этой цели, чтобы получить ссылку на parentMethod как на callParent функции(), но без вызова его:

/** 
* Returns reference to the parent class method. Works as {@link Ext.Base#callParent}, but doesn't invoke the 
* method. 
* @return {Function} Parent class method. 
*/ 
getParentMethod: function() { 
    var method, 
     superMethod = (method = this.getParentMethod.caller) && (method.$previous || 
      ((method = method.$owner ? method : method.caller) && method.$owner.superclass[method.$name])); 
    return superMethod; 
}, 


sampleMethod: function() { 
    var parentMethod = this.getParentMethod(); 
    var parentArguments = arguments; 
    someAsyncFunc(function() { 
     parentMethod.apply(this, parentArguments); // calls parent.sampleMethod(...) 
    }, this); 
}