【发布时间】:2017-04-23 15:15:10
【问题描述】:
我有这个实现:
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 需要它。换句话说,它永远不会在需要时调用:)。
有什么方法可以等待第一部分完成而不是像现在这样调用它?我的意思是它是异步调用,但现在我想它甚至比同步慢。
附:我知道 JS 中有新的Promise 功能,但是这个版本中的 Odoo 目前使用的是 jQuery deferred,所以我也在使用它。
更新
为了更好地说明情况,我将尝试描述结构、当前所做的工作以及问题所在。
这个系统有两个部分,后端(由 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 的方式)。
基本上,它会检查每个可见的日历日期,并与后端输入的日期进行比较。
也许这张图片更能说明此功能的工作原理。绿色背景的日期实际上是作为特殊日期在后端输入的日期。
【问题讨论】:
-
避免使用deferred antipattern!你甚至没有在任何地方解决你的
def? -
@Bergi 我是 deferred 的新手,所以这就是为什么这段代码看起来很奇怪。我自己知道是这样,只是还不能理解如何正确使用 deferred。
-
如果您能建议如何改进该代码,那就太好了。
-
@Roamer-1888 密钥格式为
YYYY-MM-DD。起初我只想返回代表 1970 年开始的时间的数字,但由于某种原因,JS 在日期中也包含时区,因此当日期实际上相同时,后端和 JS 之间的数字不匹配。虽然我正在寻找不同类型的代码改进 -deferred被正确使用。 -
您想在一次调用中处理多个日期-单元格对吗?还是您需要为一对日期单元格分别进行多次调用?
标签: javascript jquery asynchronous odoo-8 jquery-deferred