日历服务:使用 PropertiesService 存储和检索事件
Calendar Service: Store and retrieve events using PropertiesService
这个代码
var cal = CalendarApp.getCalendarById("Calendar Id");
var startTime = new Date(1850, 0, 1);
var endTime = new Date(2100, 0, 1);
var events = cal.getEvents(startTime, endTime);
Logger.log(events);
var sp = PropertiesService.getScriptProperties();
sp.setProperty("events", JSON.stringify(events));
events = JSON.parse(sp.getProperty("events"));
Logger.log(events);
returns:
Info [CalendarEvent, CalendarEvent, CalendarEvent, CalendarEvent, CalendarEvent]
Info [{}, {}, {}, {}, {}]
这是为什么?怎么了?
这是为什么?
CalendarEvent
是一个 Google Apps 脚本 class,事件是其实例。
检查 属性 所有权和可枚举性产生以下结果:
function stringified() {
const event = CalendarApp.createAllDayEvent('Party', new Date());
const eventToString = JSON.stringify(event);
Logger.log(eventToString); // -> {}
Logger.log(Object.keys(event)); // -> []
Logger.log(Object.getOwnPropertyNames(event)); // -> [toString,...]
Logger.log(Object.getPrototypeOf(event)); // -> {}
Logger.log(event.toString()); // -> CalendarEvent
}
这告诉我们什么?
- 没有我们可以访问的 enumerable 属性(参见
Object.keys()
)。
- 有自己的道具(参见
getOwnPropertyNames()
)。
CalendarEvent
继承自 Object
1(参见 toString()
)。
现在,看看 JSON.stringify()
对对象做了什么(这是来自 MDN 的描述,但是如果你深入研究 ECMAScript 规范,你会看到 SerializeJSONObject
operation 取决于摘要 EnumerableOwnPropertyName
):
所有其他对象实例(包括 Map、Set、WeakMap 和 WeakSet)将仅序列化它们的可枚举属性
这引出了您的第二个问题:
怎么了?
由于没有可枚举的自身属性,序列化结果为"{}"
。
怎么办?
使用 PropertiesService
存储事件没有多大意义 - 即使您想出了一种存储方法,您也会很快遇到较大事件集合的配额问题。什么,是存储一个reference,那么使用getId()
方法存储和getEventById()
检索怎么样?
样本
//...get event somehow
const store = PropertiesService.getUserProperties();
store.deleteProperty('events'); // demo only
const eventIds = store.getProperty('events') || '[]';
const id = event.getId();
const idList = JSON.parse(eventIds);
idList.push(id);
store.setProperty('events',JSON.stringify(idList));
Logger.log(store.getProperty('events'));
还能做什么?
使用日历 API(不要忘记首先通过转至 Resources
-> Cloud Platform project
-> APIs and Services
-> 为您的 GCP 项目启用它Library
)。这个 API 是一个 REST API,您可以像这样使用良好的旧 HTTP 请求进行查询:
function listEvents() {
const calendar = CalendarApp.getCalendarById('yourEmailHere');
const endpoint = `https://www.googleapis.com/calendar/v3/calendars/${calendar.getId()}/events`;
const query = {};
const preparedQuery = Object
.entries(query)
.map(param =>`${param[0]}=${param[1]}`)
.join('&');
const resp = UrlFetchApp.fetch(`${endpoint}?${preparedQuery}`,{
headers: {
Authorization: 'Bearer ' + ScriptApp.getOAuthToken()
}
});
if(resp.getResponseCode() === 200) {
//process the response
}
}
请注意,必须将 OAuth 范围设置为与 JWT 令牌(通过 getOAuthToken()
获得)一起传递。如果应用程序清单中有明确的范围列表(appscript.json
的 oauthScopes
字段),请添加 "https://www.googleapis.com/auth/calendar.events.readonly"
或更合适的。
备注
- 我的意思是,由于原型继承,
CalendarEvent
的一个实例有一个对象作为其原型。
- 使用
getUserProperties()
比 getScriptProperties()
更可取,除非需要脚本范围的设置(请参阅参考资料中的官方指南)。脚本属性在用户之间共享,并计入脚本所有者的配额。
- 要使用第二个示例,V8 运行时必须是 enabled(从问题示例中不清楚是否使用它)。
参考
- 可枚举性 explanation MDN
JSON.stringify()
docs 在 MDN
- 日历事件
getId()
docs
getEventById()
docs
- 日历APIreference
- OAuth scopes 对于 Google APIs
PropertiesService
guide
这个代码
var cal = CalendarApp.getCalendarById("Calendar Id");
var startTime = new Date(1850, 0, 1);
var endTime = new Date(2100, 0, 1);
var events = cal.getEvents(startTime, endTime);
Logger.log(events);
var sp = PropertiesService.getScriptProperties();
sp.setProperty("events", JSON.stringify(events));
events = JSON.parse(sp.getProperty("events"));
Logger.log(events);
returns:
Info [CalendarEvent, CalendarEvent, CalendarEvent, CalendarEvent, CalendarEvent]
Info [{}, {}, {}, {}, {}]
这是为什么?怎么了?
这是为什么?
CalendarEvent
是一个 Google Apps 脚本 class,事件是其实例。
检查 属性 所有权和可枚举性产生以下结果:
function stringified() {
const event = CalendarApp.createAllDayEvent('Party', new Date());
const eventToString = JSON.stringify(event);
Logger.log(eventToString); // -> {}
Logger.log(Object.keys(event)); // -> []
Logger.log(Object.getOwnPropertyNames(event)); // -> [toString,...]
Logger.log(Object.getPrototypeOf(event)); // -> {}
Logger.log(event.toString()); // -> CalendarEvent
}
这告诉我们什么?
- 没有我们可以访问的 enumerable 属性(参见
Object.keys()
)。 - 有自己的道具(参见
getOwnPropertyNames()
)。 CalendarEvent
继承自Object
1(参见toString()
)。
现在,看看 JSON.stringify()
对对象做了什么(这是来自 MDN 的描述,但是如果你深入研究 ECMAScript 规范,你会看到 SerializeJSONObject
operation 取决于摘要 EnumerableOwnPropertyName
):
所有其他对象实例(包括 Map、Set、WeakMap 和 WeakSet)将仅序列化它们的可枚举属性
这引出了您的第二个问题:
怎么了?
由于没有可枚举的自身属性,序列化结果为"{}"
。
怎么办?
使用 PropertiesService
存储事件没有多大意义 - 即使您想出了一种存储方法,您也会很快遇到较大事件集合的配额问题。什么,是存储一个reference,那么使用getId()
方法存储和getEventById()
检索怎么样?
样本
//...get event somehow
const store = PropertiesService.getUserProperties();
store.deleteProperty('events'); // demo only
const eventIds = store.getProperty('events') || '[]';
const id = event.getId();
const idList = JSON.parse(eventIds);
idList.push(id);
store.setProperty('events',JSON.stringify(idList));
Logger.log(store.getProperty('events'));
还能做什么?
使用日历 API(不要忘记首先通过转至 Resources
-> Cloud Platform project
-> APIs and Services
-> 为您的 GCP 项目启用它Library
)。这个 API 是一个 REST API,您可以像这样使用良好的旧 HTTP 请求进行查询:
function listEvents() {
const calendar = CalendarApp.getCalendarById('yourEmailHere');
const endpoint = `https://www.googleapis.com/calendar/v3/calendars/${calendar.getId()}/events`;
const query = {};
const preparedQuery = Object
.entries(query)
.map(param =>`${param[0]}=${param[1]}`)
.join('&');
const resp = UrlFetchApp.fetch(`${endpoint}?${preparedQuery}`,{
headers: {
Authorization: 'Bearer ' + ScriptApp.getOAuthToken()
}
});
if(resp.getResponseCode() === 200) {
//process the response
}
}
请注意,必须将 OAuth 范围设置为与 JWT 令牌(通过 getOAuthToken()
获得)一起传递。如果应用程序清单中有明确的范围列表(appscript.json
的 oauthScopes
字段),请添加 "https://www.googleapis.com/auth/calendar.events.readonly"
或更合适的。
备注
- 我的意思是,由于原型继承,
CalendarEvent
的一个实例有一个对象作为其原型。 - 使用
getUserProperties()
比getScriptProperties()
更可取,除非需要脚本范围的设置(请参阅参考资料中的官方指南)。脚本属性在用户之间共享,并计入脚本所有者的配额。 - 要使用第二个示例,V8 运行时必须是 enabled(从问题示例中不清楚是否使用它)。
参考
- 可枚举性 explanation MDN
JSON.stringify()
docs 在 MDN- 日历事件
getId()
docs getEventById()
docs- 日历APIreference
- OAuth scopes 对于 Google APIs
PropertiesService
guide