gpt4 book ai didi

google-apps-script - 如何使库与调用者脚本 PropertiesService 一起工作?

转载 作者:行者123 更新时间:2023-12-03 16:55:21 26 4
gpt4 key购买 nike

直到谷歌 extends the import/export API to container-bound Apps Script projects ,我已经将我的大部分项目移动到一个可以使用该 API 的库中,然后将 Google Docs 项目变成一个只调用该库的 shell。

我的问题是让库访问与 Google Doc 项目相同的属性( PropertiesService )。由于我有我的 Docs 插件的现有用户,我需要继续使用这些属性。

在我的 Google Doc 项目中,我尝试过

$.PropertiesService = PropertiesService;

(其中 $ 是我的图书馆)。

它没有用。该库继续使用自己的属性。

所以我尝试了:
function _mock(obj) {
var ret = {};
for(var key in obj) {
if(typeof obj[key] == 'function') {
ret[key] = obj[key].bind(obj);
} else {
ret[key] = obj[key];
}
}
return ret;
}

$.PropertiesService = _mock(PropertiesService);

还是行不通。再试一次:
function _mock(obj) {
var ret = {};
for(var key in obj) {
if(typeof obj[key] == 'function') {
ret[key] = (function(val) {
return function() {
return val.apply(obj, arguments);
};
})(obj[key]);
} else {
ret[key] = obj[key];
}
}
return ret;
}

$.PropertiesService = _mock(PropertiesService);

这行得通。

在这一点上,我想知道:
  • 为什么前两种方法不起作用,而第三种方法却起作用了?
  • 我可以期待这继续工作吗?
  • 有没有更好的方法让库访问主脚本的属性?

  • 文档很少。有 this ,但 PropertiesService没有提到。

    最佳答案

    资源共享
    如您所知,libraries有共享资源和非共享资源。 PropertiesService列在非共享资源下,这意味着库有自己的服务实例,当您在库代码中引用它时可以访问该实例。

    const getStore = () => PropertiesService.getScriptProperties();
    如果上面的函数在库中声明,它将使用库的资源,如果在调用脚本中 - 它自己的实例。

    V8运行时解决方案
    V8 运行时 does not create a special context为您的代码,并让您直接访问内置服务。因此,在使用运行时时,可以通过简单地定义或替换全局 this 上的属性来注入(inject)服务。 :
    //in the library;
    var getProperty = ((ctxt) => (key) => {
    var service = ctxt.injectedService;
    var store = service.getScriptProperties();
    return store.getProperty(key);
    })(this);

    var setProperty = ((ctxt) => (key, val) => {
    var service = ctxt.injectedService;
    var store = service.getScriptProperties();
    return store.setProperty(key, val);
    })(this);

    var inject = ((ctxt) => (service) => ctxt.injectedService = service)(this);

    var greet = ((ctxt) => () => {
    var store = ctxt.injectedService.getScriptProperties();
    return store.getProperty("greeting") || "Ola!";
    })(this);

    //in the calling script;
    function testSharedResources() {
    PropertiesService.getScriptProperties().setProperty("greeting", "Hello, lib!");
    $.inject(PropertiesService);
    Logger.log($.greet()); //Hello, lib!
    $.setProperty("greeting", "Hello, world!");
    Logger.log($.greet()); //Hello, world!
    }
    在某些情况下,全局 this将是 undefined (我在将库添加到绑定(bind)脚本时遇到了这个问题)。在这种情况下,只需定义一个私有(private)全局命名空间(以避免泄漏到调用者脚本):
    //in the library;
    var Dependencies_ = {
    properties : PropertiesService
    };

    var use = (service) => {
    if ("getScriptProperties" in service) {
    Dependencies_.properties = service;
    }
    };

    //in the calling script;
    $.use(PropertiesService);

    Rhino 运行时解决方案
    另一方面,较旧的 Rhino 运行时会创建一个特殊的隐式上下文。这意味着您无法访问内置服务或全局 this .您唯一的选择是绕过调用库中的服务(您的方法#3 非常适合这样做)。

    问题
  • 为什么前两种方法不起作用,而第三种方法却起作用了?

  • 您的方法的所有问题归结为:
  • 资源共享(图书馆有自己的服务实例)
  • 特殊的隐式上下文(Rhino 中无法从外部访问内置的 lib)

  • 但是有一个问题:所有 3 种方法都按设计工作。
    首先,如果您特别引用 PropertiesService,则方法一确实有效。在 $ .这是有道理的,因为库是作为 namespace 包含的,其成员映射到库中的全局声明。例如:
    //in the caller script
    PropertiesService.getScriptProperties().setProperty("test", "test");
    $.PropertiesService = PropertiesService;

    Logger.log( $.PropertiesService.getScriptProperties().getProperty("test") ); // "test"
    Logger.log( $.getProperty("test") ); // "null"

    //in the library
    function getProperty(key) {
    var store = PropertiesService.getScriptProperties();
    return store.getProperty(key);
    }
    方法二也有效。如果在库中调用它接收库上下文,调用者脚本中的函数绑定(bind)不会改变这一事实,但如果您直接在调用脚本中调用绑定(bind)副本,它会起作用:
    //in the caller script
    PropertiesService.getScriptProperties().setProperty("test", "test");
    var bound = $.PropertiesService.getScriptProperties.bind(PropertiesService);

    var obj = { getScriptProperties : bound };

    $.PropertiesService = obj;

    Logger.log( bound().getProperty("test") ); // "test"
    Logger.log( $.getProperty("test") ); // "null"
    现在,为什么第三种方法开箱即用?由于捕获 PropertiesService 的包装函数导致的闭包调用脚本并应用 getScriptProperties方法。为了显示:
    //in the caller script
    var appl = {
    getScriptProperties : (function(val) {
    return function() {
    return val.apply(PropertiesService);
    };
    })(PropertiesService.getScriptProperties)
    };

    $.PropertiesService = appl;

    Logger.log( $.getProperty("test") ); // "test"
  • 我可以期待这继续工作吗?

  • 是和不是。是的,因为您的 _mock函数行为在所有情况下都表现出预期的行为。不,因为 apply依赖 getScriptProperties没有被实现为箭头函数,其中 this覆盖将被忽略。
  • 有没有更好的方法让库访问主脚本的属性?

  • 对于 Rhino 运行时 - 不要这么认为。对于 V8 - 直接注入(inject)服务就足够了。

    关于google-apps-script - 如何使库与调用者脚本 PropertiesService 一起工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22818320/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com