如何从JavaScript promises(python调用)获取变量,避免Odoo中的挂起状态?

时间:2017-12-15 14:05:02

标签: javascript asynchronous promise odoo-8 odoo

销售点模块的原始代码

point_of_sale模块中,有一个对象列表,如下所示

module.PosModel = Backbone.Model.extend({

    models: {

        // [...]

        {
            model:  'pos.session',
            fields: ['id', 'journal_ids','name','user_id','config_id','start_at','stop_at','sequence_number','login_number'],
            domain: function(self){ return [['state','=','opened'],['user_id','=',self.session.uid]]; },
            loaded: function(self,pos_sessions){
                self.pos_session = pos_sessions[0]; 

                var orders = self.db.get_orders();
                for (var i = 0; i < orders.length; i++) {
                    self.pos_session.sequence_number = Math.max(self.pos_session.sequence_number, orders[i].data.sequence_number+1);
                }
            },
        },
        {
            model:  'product.product',
            fields: ['display_name', 'list_price','price','pos_categ_id', 'taxes_id', 'ean13', 'default_code', 
                        'to_weight', 'uom_id', 'uos_id', 'uos_coeff', 'mes_type', 'description_sale', 'description',
                        'product_tmpl_id'],
            domain: [['sale_ok','=',true],['available_in_pos','=',true]],
            context: function(self){ return { pricelist: self.pricelist.id, display_default_code: false }; },
            loaded: function(self, products){
                self.db.add_products(products);
        },

        // [...]

    }

然后像这样加载数据的信息

load_server_data: function(){
    var self = this;
    var loaded = new $.Deferred();
    var progress = 0;
    var progress_step = 1.0 / self.models.length;
    var tmp = {}; // this is used to share a temporary state between models loaders

    function load_model(index){
        if(index >= self.models.length){
            loaded.resolve();
        }else{
            var model = self.models[index];
            self.pos_widget.loading_message(_t('Loading')+' '+(model.label || model.model || ''), progress);
            var fields =  typeof model.fields === 'function'  ? model.fields(self,tmp)  : model.fields;
            var domain =  typeof model.domain === 'function'  ? model.domain(self,tmp)  : model.domain;
            var context = typeof model.context === 'function' ? model.context(self,tmp) : model.context; 
            var ids     = typeof model.ids === 'function'     ? model.ids(self,tmp) : model.ids;
            progress += progress_step;


            if( model.model ){
                if (model.ids) {
                    var records = new instance.web.Model(model.model).call('read',[ids,fields],context);
                } else {
                    var records = new instance.web.Model(model.model).query(fields).filter(domain).context(context).all()
                }

// [...]

我尝试过的。首先尝试

所以,我想更改product.product模型的域字段。我正在尝试这个

if (typeof jQuery === 'undefined') { throw new Error('Product multi POS needs jQuery'); }

+function ($) {
    'use strict';

    openerp.pos_product_multi_shop = function(instance, module) {
        var PosModelParent = instance.point_of_sale.PosModel;
        instance.point_of_sale.PosModel = instance.point_of_sale.PosModel.extend({
            load_server_data: function(){
                console.log('-- LOAD SERVER DATA');
                var self = this; 

                self.models.forEach(function(elem) {
                    if (elem.model == 'product.product') {
                        // return [['id', 'in', [2]]];    // if I return this domain it works well
                        domain_loaded = function() {
                            return new instance.web.Model('product.product').call(
                                'get_available_in_pos_ids',
                                [self.pos_session.config_id[0]],
                            )
                        }
                        elem.domain = $.when(domain_loaded);
                    }
                })

                var loaded = PosModelParent.prototype.load_server_data.apply(this, arguments);
                return loaded;
            },
        });
    }
}(jQuery);

如果我直接返回一个域名就行了。但是如果我用一个用call调用python函数的函数替换它,那么域的加载不会很好:[['sale_ok','=',true],['available_in_pos','=',true]]。我已尝试使用$.when而没有它,但它不起作用。

此外,elem.domain必须是一个函数,因为self.pos_session仅在执行所有先前的模型信息时才存在。

第二次尝试

我也试过以下代码:

if (elem.model == 'product.product') {
    // return [['id', 'in', [2]]];    // if I return the domain like this it works
    console.log('>> OLD DOMAIN')
    console.log(elem.domain);
    elem.domain = function() {
        console.log('>>> PRODUCT SESSION');
        console.log(self.pos_session);
        var product_product_obj = new instance.web.Model('product.product');
        return product_product_obj.call(
            'get_available_in_pos_ids',
            [self.pos_session.config_id[0]],
        )
    }
    console.log('>> NEW DOMAIN')
    console.log(elem.domain);
}

首先&#39;&gt;&gt;老域&#39;打印,然后&gt;&gt;&gt;新域名&#39;最后&#39;&gt;&gt;&gt;产品会议&#39;打印出来。所以该函数被执行。但这些领域并未得到很好的回报。

第三次尝试。使用&#34;然后&#34;

我无法使用then,因为我需要进行变量赋值。但另一方面,分配工作做得很好,因为当我打印新域时,该功能会出现在日志中。

即使我使用then,我也可以从python

中获得结果
var domain_return = product_product_obj.call(
    'get_available_in_pos_ids',
    [self.pos_session.config_id[0]],
).then(function(result) {
    console.log('>> RESULT: ');
    console.log(result)
});

我也尝试了其他承诺,但是我得到了一个被忽略的待处理结果,并显示了所有产品

elem.domain = function() {
    return new Promise(function next(resolve, reject) {
        console.log('>>> PRODUCT SESSION');
        console.log(self.pos_session);
        var product_product_obj = new instance.web.Model('product.product');
        var domain_return = product_product_obj.call(
            'get_available_in_pos_ids',
            [self.pos_session.config_id[0]],
        ).then(function(result) {
            console.log('>> RETURN: ');
            console.log(result);
            resolve(result);
        });
        console.log('>> DOMAIN RETURN: ');
        console.log(domain_return);
    });
}

在不调用python函数的情况下计算对象的其余域。所以我无法从其他地方复制一个例子

那么,有没有办法避免待定结果?我还不能使用async/await

也许让它同步会有所帮助,但我知道这应该避免

1 个答案:

答案 0 :(得分:0)

最后,我找到了一个解决方法,覆盖已加载所有产品的已加载函数

var PosModelParent = instance.point_of_sale.PosModel;
instance.point_of_sale.PosModel = instance.point_of_sale.PosModel.extend({
    load_server_data: function(){
        let self = this;
        self.models.forEach(function(elem) {
            if (elem.model == 'product.product') {
                elem.fields = ['display_name', 'list_price','price','pos_categ_id', 'taxes_id', 'ean13', 'default_code', 
                'to_weight', 'uom_id', 'uos_id', 'uos_coeff', 'mes_type', 'description_sale', 'description',
                'product_tmpl_id', 'available_in_pos_ids'];
                elem.loaded = function(self, products){
                    console.log('>> PRODUCTS: ');
                    console.log(products);
                    var shop_id = self.pos_session.config_id[0];                            
                    var new_products = [];
                    products.forEach(function(prod) {
                        if (prod.available_in_pos_ids.includes(shop_id)) {
                            new_products.push(prod);
                        }
                    })
                    self.db.add_products(new_products);
                }
            }
        })
        var loaded = PosModelParent.prototype.load_server_data.apply(this, arguments);
        return loaded;
    },
});