我正在处理需要有条件地向最终用户公开API的产品。我们正在使用Closure Compiler进行缩小。我尝试公开的API的一部分是一个函数,它调用一个Result
的回调,其值是具有某些属性的对象。
具体来说,我尝试公开的函数看起来像这样(用伪jsdoc表示法):
/**
* @type DocumentRenderResult {status: String, image?: HTMLImageElement|HTMLCanvasElement}
* @param {function(Result<DocumentRenderResult>)} callback
**/
function renderDocument (url, page, callback) {
}
Result
类看起来像这样:
/**
* @template T
* @param {Boolean} ok
* @param {T} val
* @param {Error} err
**/
function Result (ok, val, err) {
this.ok = ok;
this.val = val;
this.err = err;
}
我想要的是公开Result
对象API,即有ok
,val
和err
属性的事实,并公开renderDocument
界面,以便提供回调的用户能够访问status
和image
属性。
一个解决方案(可能)是在任何地方使用括号表示法,但由于这应该只是有条件地暴露(对于某些最终用户),我想分开概念是否从代码中缩小了。
我认为@implements和@export以及externs文件的某些组合可以实现这一点,但我还没有想到它。
我正在尝试做什么?
答案 0 :(得分:1)
有两种主要方法可以解决这种情况:
将所有导出存储在一个单独的文件中,该文件将成为api公开库的主要入口点。此方法不依赖于外部库。有关此示例,请参阅我的GeolocationMarker library。
如果您愿意在项目中使用闭包库代码的一小部分,则可以使用@export
注释。除非指定了编译标记@export
,否则--generate_exports
注释不会执行任何操作。
当使用--generate_exports
时,编译器会将相应的调用添加到closure-library的goog.exportProperty或goog.exportSymbol方法。
/** @const */
var mynamespace = {};
/** @export */
mynamespace.maybeExposedMethod = function() {};
使用--generate_exports
标志,编译器将生成代码:
var mynamespace = {maybeExposedMethod:function() {}};
goog.exportSymbol("mynamespace.maybeExposedMethod",
mynamespace.maybeExposedMethod);
而不是必须依赖所有的闭包库。您可以将这两种方法的定义复制到源中。所需要的只是它们以那些名字存在。
必须区别对待返回匿名对象的函数以防止重命名。这里最好的选择是在自己的文件中定义记录类型。对于公共api阻止重命名,请将记录定义包含为extern。如果希望重命名记录属性,请将定义包括为源。
<强> my_typedefs.js 强>
/** @typedef {{image: string, status: number}} */
var my_record_type;
<强> my_method_def.js 强>
/** @return {my_record_type} */
function my_method() {
return {
image: 'some_image.jpg',
status: 200
};
}
如果编译中包含my_typedefs.js
--js
标志,则会重命名记录属性,但如果它包含在--externs
标志中,则不会重命名。