简体   繁体   中英

How to catch promise before calling this._super? Javascript

I would like to get result from my request "instance.web.Model", then call this.super(). The matter is that "instance.web.Model" is asynchronous, so in my case the super() will be called before the request has finished.

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.

    }
});

Do you know how to get through that? In order to pass the newData instead data as argument to the super object.

PS : I tried to encapsulate this in self : var self = this; but it does not work because it seems the parent object I extend continue to run without waiting. So I got error like "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
        });

    }
});

To answer Bergi, as he asked I what _super() is calling. The instance.web.Model call a python script in server-side, I guess it is kind of Ajax call. But I test many case and I assume this instance.web.Model call is asynchronous. So that is the object I extend :

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

To go further (hope it will help you). Ok, let's see who are the superclass:

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

Then, the next one:

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

Then :

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

Then:

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

Finally:

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

I don't think the dynamic super method that is provided by the most frameworks does work asynchronously - but if you use promises, it does need to (promises are always asynchronous).

So if you need to call the parent's initialisation method from the promise callback, you can either try

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

or don't use _super at all but the native capability to reference your parent class:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM