【问题标题】:How to catch promise before calling this._super? Javascript如何在调用 this._super 之前获得承诺? Javascript
【发布时间】:2014-12-02 20:39:30
【问题描述】:

我想从我的请求“instance.web.Model”中获取结果,然后调用 this.super()。问题是“instance.web.Model”是异步的,所以在我的例子中,super() 将在请求完成之前被调用。

MyObject.extend({

    init: function(parent, data){

        var newData = instance.web.Model('advanced.search')
        .call('check_duplication', [data]).done(function (name) {
            // do stuff
            return name
        });

        data = newData;
        this._super.apply(this, arguments);
        // super is called before my request is done so the new data are not sent to super.

    }
});

你知道如何度过难关吗?为了将 newData 而不是数据作为参数传递给超级对象。

PS:我试图将它封装在 self 中: var self = this;但它不起作用,因为我扩展的父对象似乎继续运行而无需等待。所以我得到了像“self.super(... is not a function”这样的错误。

MyObject.extend({

    init: function(parent, data){
        var self = this;

        var newData = instance.web.Model('advanced.search')
        .call('check_duplication', [data]).done(function (name) {
            // do stuff
            var newData = name;
            self._super.apply(self, parent, newData);
            // or self._super.apply(self, arguments); etc... I tried many variantes
        });

    }
});

回答Bergi,因为他问我 _super() 叫什么。 instance.web.Model 在服务器端调用 python 脚本,我猜它是一种 Ajax 调用。但是我测试了很多情况,我假设这个 instance.web.Model 调用是异步的。这就是我扩展的对象:

instance.web.search.ExtendedSearchProposition = instance.web.Widget.extend(/** @lends instance.web.search.ExtendedSearchProposition# */{
template: 'SearchView.extended_search.proposition',
events: {
    'change .searchview_extended_prop_field': 'changed',
    'change .searchview_extended_prop_op': 'operator_changed',
    'click .searchview_extended_delete_prop': function (e) {
        e.stopPropagation();
        this.getParent().remove_proposition(this);
    }
},
/**
 * @constructs instance.web.search.ExtendedSearchProposition
 * @extends instance.web.Widget
 *
 * @param parent
 * @param fields
 */
init: function (parent, fields) {
    this._super(parent);
    this.fields = _(fields).chain()
        .map(function(val, key) { return _.extend({}, val, {'name': key}); })
        .filter(function (field) { return !field.deprecated && (field.store === void 0 || field.store || field.fnct_search); })
        .sortBy(function(field) {return field.string;})
        .value();
    this.attrs = {_: _, fields: this.fields, selected: null};
    this.value = null;
},

更进一步(希望对您有所帮助)。好的,让我们看看谁是超类:

instance.web.Widget = instance.web.Controller.extend({
// Backbone-ish API
tagName: 'div',
id: null,
className: null,
attributes: {},
events: {},
/**
 * The name of the QWeb template that will be used for rendering. Must be
 * redefined in subclasses or the default render() method can not be used.
 *
 * @type string
 */
template: null,
/**
 * Constructs the widget and sets its parent if a parent is given.
 *
 * @constructs instance.web.Widget
 *
 * @param {instance.web.Widget} parent Binds the current instance to the given Widget instance.
 * When that widget is destroyed by calling destroy(), the current instance will be
 * destroyed too. Can be null.
 */
init: function(parent) {
    this._super(parent);
    // Bind on_/do_* methods to this
    // We might remove this automatic binding in the future
    for (var name in this) {
        if(typeof(this[name]) == "function") {
            if((/^on_|^do_/).test(name)) {
                this[name] = this[name].bind(this);
            }
        }
    }
    // FIXME: this should not be
    this.setElement(this._make_descriptive());
    this.session = instance.session;
},

然后,下一个:

instance.web.Controller = instance.web.Class.extend(instance.web.PropertiesMixin, {
/**
 * Constructs the object and sets its parent if a parent is given.
 *
 * @param {instance.web.Controller} parent Binds the current instance to the given Controller instance.
 * When that controller is destroyed by calling destroy(), the current instance will be
 * destroyed too. Can be null.
 */
init: function(parent) {
    instance.web.PropertiesMixin.init.call(this);
    this.setParent(parent);
},

然后:

instance.web.PropertiesMixin = _.extend({}, instance.web.EventDispatcherMixin, {
init: function() {
    instance.web.EventDispatcherMixin.init.call(this);
    this.__getterSetterInternalMap = {};
},

然后:

instance.web.EventDispatcherMixin = _.extend({}, instance.web.ParentedMixin, {
__eventDispatcherMixin: true,
init: function() {
    instance.web.ParentedMixin.init.call(this);
    this.__edispatcherEvents = new Events();
    this.__edispatcherRegisteredEvents = [];
},

最后:

instance.web.ParentedMixin = {
__parentedMixin : true,
init: function() {
    this.__parentedDestroyed = false;
    this.__parentedChildren = [];
    this.__parentedParent = null;
},

【问题讨论】:

  • ._super 在哪里定义?如果它是由您的框架隐式创建的(您使用哪一个?),它很可能无法异步工作。
  • 我注意到父母也调用了 this_super(),也许这是我的问题之一。很抱歉没有在我的信息中更明确,我在这个领域的经验不是那么大,所以我不知道从哪里可以得到正确的信息来展示给你
  • 我想知道MyModel 是什么,它是如何得到extend 方法的?你可能在使用 Backbone 吗?
  • 是的,有一些 Backbone.js 使用,但我不知道具体在哪里。实际上我这样做: instance.web.search.ExtendedSearchProposition.include({... 而不是 MyObject.extend({...
  • 所以你说instance.web.search.ExtendedSearchProposition 是你想通过super 调用init 的超类?

标签: javascript ajax asynchronous promise odoo


【解决方案1】:

我不认为大多数框架提供的动态 super 方法确实异步工作 - 但如果您使用承诺,它确实需要(承诺总是异步的)。

所以如果你需要从promise回调中调用父级的初始化方法,你可以试试

MyObject.extend({
    init: function(parent, data){
        var _super = this._super.bind(this);

        instance.web.Model('advanced.search')
        .call('check_duplication', [data])
        .done(function (name) {
            _super(parent, name);
        });
        // or in short, even just:
        // .done(this._super.bind(this, parent));
    }
});

或者根本不使用_super,而是使用native capability 来引用您的父类:

MyObject.extend({
    init: function(parent, data){
        var self = this;

        instance.web.Model('advanced.search')
        .call('check_duplication', [data])
        .done(function (name) {
            instance.web.search.ExtendedSearchProposition.prototype.init // or whatever the parent method is
              .call(self, parent, newData);
        });
    }
});

【讨论】:

  • 我刚刚试过你的想法:第一个 A -> SyntaxError: super 是一个保留标识符 第一个 B -> TypeError: self.super is not a function 第二个 -> TypeError: dict. widget.attrs 未定义 + 无限递归通过 .done() 范围传递 self 是有问题的
  • 糟糕,第一个是我的愚蠢错误;第二个需要适应实际的超类(显然MyObject 不是超类)
  • :) thx 但仍然存在类似情况 2 -> TypeError: dict.widget.attrs is undefined 的问题。 jQuery BlockUI 插件怎么样?我听说在我的程序中使用它
  • 我不知道dict.widget.attrs 是什么或应该是什么。
  • 是的,这很复杂,因为有数千行 JS 代码。我以为我是从我的覆盖中构思出来的,但似乎有点棘手^^
猜你喜欢
  • 1970-01-01
  • 2021-12-12
  • 2017-04-22
  • 1970-01-01
  • 2014-11-07
  • 2020-08-17
  • 2019-03-31
  • 2016-04-14
  • 2014-07-31
相关资源
最近更新 更多