google-apps-script - 您可以将 UrlFetchApp 转换为 Apps Script 中的 Promise 吗?
问题描述
UrlFetchApp.fetch 同步执行,导致执行速度变慢。是否可以将 UrlFetchApp 转换为 promise?
我一直在考虑这种方法:
- 作为 Promise返回
HTTPResponse.getContent()
并将所有 url 添加到队列中。 - 推迟它们的执行直到
getContent().then()
被调用。 - 当
getContent()
调用任何一个 url 时,用于fetchAll
获取所有结果并清除队列。
你觉得这种方法有什么问题吗?
解决方案
从理论上讲,该方法似乎是合理的,尤其是因为已知.fetchAll
异步执行。
.fetch()
call 是实际提取发生的地方。fetch
因此,应在调用之前插入 UrlFetchApp 对象的任何挂钩。您可以使用 a
Proxy object
来挂钩.fetch
调用UrlFetchApp
以返回HTTPResponse
带有对象的虚拟thenable
对象然后按照问题中的说明使用
fetchAll
on.getContent
call。但是请注意,apps 脚本中的 promise 可能会也可能不会按照问题注释 #1 到 #4中的说明异步执行。但是,这不应该是您的方法的问题。
鉴于 Promise 的挑剔性质和不明确的文档,最好在任何生产环境中避免使用它们。实现批处理请求的更好方法是使用带有thenable
对象的普通自定义函数:
function test() {
/**
* @description Batches requests until then is called on a response
* and fetches all batched requests
* @return {object} A then object, which when called fetches the batch
* @param {string} url Url to fetch
* @param {object} options Options to fetch. See UrlFetchApp.fetch
*/
const fetchAsBatch = function fetch(requests, url, options) {
options.url = url;
requests.add(options);
return {
then: func => {
const responses = func(UrlFetchApp.fetchAll([...requests]));
requests.clear();// clear current batch
return responses;
},
};
}.bind(this, new Set());
const successHandlerLogger = responses => {
/*Do something with all responses*/
console.log(responses.map(response => response.getContentText()));
};
fetchAsBatch('https://example.com', { method: 'get' });
fetchAsBatch('https://httpbin.org/post', { method: 'post' }).then(
successHandlerLogger
);
fetchAsBatch('https://google.com', {}).then(successHandlerLogger);
}
function test() {
/**
* @description Batches requests until then is called on a response
* and fetches all batched requests
* @return {object} A then object, which when called fetches the batch
* @param {string} url Url to fetch
* @param {object} options Options to fetch. See UrlFetchApp.fetch
*/
const fetchAsBatch = function fetch(requests, url, options) {
options.url = url;
requests.add(options);
return {
then: func => {
const responses = func(UrlFetchApp.fetchAll([...requests]));
requests.clear();
return responses;
},
};
}.bind(this, new Set());
const successHandlerLogger = responses => {
/*Do something with all responses*/
console.log(responses.map(response => response.getContentText()));
};
fetchAsBatch('https://example.com', { method: 'get' });
fetchAsBatch('https://httpbin.org/post', { method: 'post' }).then(
successHandlerLogger
);
fetchAsBatch('https://google.com', {}).then(successHandlerLogger);
}
/*Mock urlfetchapp library to return requests without fetch*/
const UrlFetchApp = {
fetchAll: requests =>
requests.map(request => ({
getContentText: () => request,
})),
};
test();
推荐阅读
- javascript - jquery在脚本代码中查找和替换字符串然后运行这个脚本?
- tensorflow - 导入 Tensorflow 时出现非法指令(核心转储)
- excel - 使用 vb.net 将值从 excel 单元格写入记事本
- rounding - 如何在 Kentico 商店设置中传播舍入配置以进行自定义计算?
- javascript - 从服务 Javascript 接收变量 - React Hooks
- python - Django:使用带有模型视图集的用户名查找用户 OnetoOne 字段(Django Rest API)
- github - Markdown 语法不适用于我的 GitHub 博客文章
- java - 我是Java新手,下面代码的逻辑是什么?
- eclipse - Eclipse + PyDev:使用文档字符串进行类型检查(如 PyCharm)
- java - 如何在 java 中创建一个可以包含 100 个地址簿条目的地址簿?