jQuery:保存异步调用结果以便以后使用?

时间:2017-04-23 15:15:11

标签: javascript jquery asynchronous odoo-8 jquery-deferred

我有这个实现:

    instance.web_calendar.CalendarView.include({
        handle_special_dates: function(date, cell){
            var def = $.Deferred(),
                model = new instance.web.Model('calendar.special');
            model.call('get_special_dates').then(function(result){
                // Transform date strings into date obj valueOf result.
                var new_obj = {}
                for (key in result){
                    if (result.hasOwnProperty(key)){
                        var dt_value = new Date(key).valueOf();
                        // Set new key as date.ValueOf() and use
                        // special date name as value.
                        new_obj[dt_value] = result[key]
                    }
                }
                return new_obj;
            }).then(function(result){
                // We stringify value, because object stringifies keys
                // automatically.
                var dt_value = String(date.valueOf())
                // Check if date value is in special dates keys.
                // We check for -1, because it actually returns index,
                // not a boolean value.
                if ($.inArray(dt_value, Object.keys(result)) != -1){
                    var div = $(
                        '<div />',
                        {
                            "class": 'fc-special-day',
                            text: result[dt_value]
                        }
                    )
                    cell.children('div').prepend(div)
                    // Set special day background
                    cell.addClass('fc-special-background')

                }
            })
            return def;
        },
        get_fc_init_options: function(){
            var self = this;
            fc_options = this._super()
            if (this.special_dates){
                return $.extend({}, fc_options, {
                    dayRender: function(date, cell){
                        self.handle_special_dates(date, cell)
                    }
                });
            } else {
                return fc_options;
            }
        },
    })
}
在系统后端定义的

handle_special_dates函数调用方法(这是异步调用),解析结果并使用它来检查我们是否需要修改日历的cell

问题是两个then部分被调用的次数与要检查的单元格一样多。所以这有点笨重,因为我只需要调用一次后端,然后对所有单元格使用结果。

基本上第一个then(调用get_special_dates后端方法的那个)部分应该只被调用一次。我尝试将该功能分开,但随后会在dayRender之后调用它。换句话说,它永远不会在需要时调用:)。

有没有办法以某种方式等待第一部分完成而不是像现在这样调用它?我的意思是它是异步调用,但现在我猜它甚至比同步更慢。

P.S。我知道JS中有新的Promise功能,但是这个版本中的Odoo目前使用jQuery延迟,所以我也使用它。

更新

为了更好地解释这种情况,我将尝试描述结构,目前的工作以及问题所在。

这个系统有两个部分,后端(由Python管理)和前端(Javascript)。

后端管理前端可以使用的数据。具体而言,后端有一种名为get_special_dates的方法。它返回名为calendar_special的特定表中输入名称的日期。因此,如果有人输入任何此类日期,它将返回其日期字符串表示(和名称)。例如,我们可以输入日期2017-04-16并将其命名为Easter

现在,当Javascript部分加载日历界面时,它会检查所有当前可见的日历日期,并与get_special_dates返回的日期进行比较。如果比较日期匹配,则会在日历中标记它们。

但问题是get_special_dates现在被称为,因为检查每个日期/单元格对。假设我们在一个月内有30个日期,并且我们看到该月的30个日期,它会调用get_special_dates 30次,而实际上只有一次调用就足够了(因为来自后端的日期)对于所有日期/单元格对检查都是相同的)。但我需要保存结果以便重用所有日期/单元格对(或其他适用于deferred的方式)。

基本上它会检查每个可见的日历日期,并与后端输入的内容进行比较。

也许这张图片更能说明这项功能是如何运作的。具有绿色背景的日期实际上是在后端作为特殊日期输入的日期。

enter image description here

1 个答案:

答案 0 :(得分:1)

你问的是有效的,&#34;我如何缓存承诺?&#34;。

简单的答案是&#34;将其分配给合适范围内的成员,从中可以在任何需要的地方进行访问。&#34;

这里, &#34;成员在合适的范围内&#34; (不一定是唯一的一个)是handle_special_dates()属性的对象,(除非handle_special_dates()以奇数方式调用)将来自this handle_special_dates()

除了缓存承诺之外,您还可以通过在缓存点链接两个中的第一个来执行new_obj转换。

specialDatesPromise: null, // not strictly necessary but makes the cache overt. 
handle_special_dates: function(date, cell) {
    // if promise doesn't already exist, call() and cache
    if(!this.specialDatesPromise) {
        this.specialDatesPromise = (new instance.web.Model('calendar.special')).call('get_special_dates')
        .then(function(specialDates) {
            // for economy of effort, perform transform at point of caching
            var new_obj = {};
            $.each(specialDates, function(key, value) {
                new_obj[new Date(key).valueOf()] = value;
            });
            return new_obj;
        });
    }
    // Now use the cached promise - it may be newly or previously cached - doesn't matter which.
    return this.specialDatesPromise.then(function(result) {
        var dt_value = String(date.valueOf());
        if (result[dt_value] !== undefined) {
            cell.addClass('fc-special-background').children('div').prepend($('<div/>', {
                'class': 'fc-special-day',
                'text': result[dt_value]
            }));
        }
    });
},

进一步简化应该有效,除非我犯错误/误解。

请注意,jQuery.Deferred()不需要.call('get_special_dates'),因为{{1}}会返回可行的承诺。