如何在调用 this._super 之前捕获 Promise?JavaScript

use*_*239 2 javascript ajax asynchronous promise odoo

我想从我的请求“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.

    }
});
Run Code Online (Sandbox Code Playgroud)

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

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

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
        });

    }
});
Run Code Online (Sandbox Code Playgroud)

回答 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;
},
Run Code Online (Sandbox Code Playgroud)

更进一步(希望它能帮助你)。好吧,让我们看看谁是超类:

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;
},
Run Code Online (Sandbox Code Playgroud)

然后,下一篇:

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);
},
Run Code Online (Sandbox Code Playgroud)

然后 :

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

然后:

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

最后:

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

Ber*_*rgi 6

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

因此,如果您需要从 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));
    }
});
Run Code Online (Sandbox Code Playgroud)

或者根本不使用_super,只使用本机功能来引用您的父类:

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);
        });
    }
});
Run Code Online (Sandbox Code Playgroud)