如何使用jsdoc记录回调的正确方式?

105

我在网上搜索了很久,寻找用jsdoc正确记录回调函数的最佳方法,但不幸的是,我还没有找到一个很好的方法。

这是我的问题:

我正在为开发人员编写一个Node.js库。该库提供多个类、函数和方法供开发人员使用。

为了使我的代码清晰易懂,并且(希望)能够在未来自动生成一些API文档,我开始在我的代码中使用jsdoc来自我记录发生了什么。

假设我定义了以下函数:

function addStuff(x, y, callback) {
  callback(x+y);
});

使用 jsdoc,我当前将此函数记录为以下内容:

/**
  * Add two numbers together, then pass the results to a callback function.
  *
  * @function addStuff
  * @param {int} x - An integer.
  * @param {int} y - An integer.
  * @param {function} callback - A callback to run whose signature is (sum), where
  *  sum is an integer.
  */
function addStuff(x, y, callback) {
  callback(x+y);
});

我觉得上面的解决方案有点hack-ish,因为我无法绝对地指定回调函数应该接受什么。

理想情况下,我想做类似这样的事情:

/**
  * Add two numbers together, then pass the results to a callback function.
  *
  * @function addStuff
  * @param {int} x - An integer.
  * @param {int} y - An integer.
  * @param {callback} callback - A callback to run.
  * @param {int} callback.sum - An integer.
  */
function addStuff(x, y, callback) {
  callback(x+y);
});

上述内容似乎可以让我更简单地传达我的回调函数需要接受什么。这有意义吗?

我想我的问题很简单:用jsdoc清晰地记录回调函数的最佳方法是什么?

感谢您花费时间。


1
可能是如何使用JSDoc记录回调函数?的重复问题。 - Victor Sergienko
5个回答

138

JSDoc 3有一个@callback标签专门用于此目的。以下是使用示例:

/**
 * Callback for adding two numbers.
 *
 * @callback addStuffCallback
 * @param {int} sum - An integer.
 */

/**
 * Add two numbers together, then pass the results to a callback function.
 *
 * @param {int} x - An integer.
 * @param {int} y - An integer.
 * @param {addStuffCallback} callback - A callback to run.
 */
function addStuff(x, y, callback) {
  callback(x+y);
}

33
Visual Studio IDE 不支持这个。这里的另一个答案 @param {function(int):void} callback 可以在 VS 中使用,而且更加简洁。 - user6269864
这是我最终在Visual Code中所做的。 - luis.espinal
1
如果这是一个回调函数来添加两个数字,那么回调函数应该有两个参数。我认为我们希望回调行说callback(x,y)并在回调文档字符串中添加另一个@param。 - johnklawlor
@johnklawlor,我不这样认为。 这是 OP 简化了问题。 当他的库完成使用其他地方获得的两个数字(在此情况下可能是早期但从他的 addStuff 方法中)工作后,通过调用由客户端提供的 callback 函数将结果返回给客户端。 该问题的目标是向客户端,即库的用户,清楚说明该回调函数应具有哪些参数。 客户端将具有任何名称的函数:function addStuffResult( res ) { /* do stuff with res */ } - aamarks

62

另一种可能是这样描述传递给回调函数的值:

Another possibility is to describe the value passed to the callback this way:

/**
  * Add two numbers together, then pass the results to a callback          function.
  *
  * @function addStuff
  * @param {int} x - An integer.
  * @param {int} y - An integer.
  * @param {function(int)} callback - A callback to run whose signature is (sum), where
  *  sum is an integer.
  */
function addStuff(x, y, callback) {
    callback(x+y);
});

要记录回调函数的返回类型,请使用@param {function(int):string}


2
我喜欢这种方法,因为我的IDE(Netbeans)支持它,但似乎无法识别@callback标记。 - Justin Emery
2
包括 function(int) 的返回值怎么样? - Maslow
10
“@Maslow function(int):string (as an example)”这个例子在Visual Studio Code中对我有效。 - Inkling
1
刚刚发现使用 @param {function(error):void} callback - 如果没有错误发生,则返回 null。 是可以工作的,但它会显示 "arg0: any"。测试后发现,为了让 Visual Studio Code 显示正确的类型,error 必须是 Error。我不明白的是,我已经阅读了很多帖子和问题,说在编写类型时大小写不敏感。不过,在 JavaScript 中,小写应该适用于原始类型,例如 number。只是想提醒其他人遇到同样问题时注意一下。 - Nova
@Nova Error 不是原始类型吗? - yyny
错误是一个非原始类型,我相信。 - Nova

10

让VSCode理解它的解决方法

/**
 * @typedef {function(FpsInfo)} fpsCallback
 * @callback fpsCallback
 * @param {FpsInfo} fps Fps info object
 */

 /**
 * @typedef {Object} FpsInfo
 * @property {number} fps The calculated frames per second
 * @property {number} jitter The absolute difference since the last calculated fps
 * @property {number} elapsed Milliseconds ellapsed since the last computation
 * @property {number} frames Number of frames since the last computation
 * @property {number} trigger Next computation will happen at this amount of frames
 */

/**
 * FPS Meter - Returns a function that is used to compute the framerate without the overhead of updating the DOM every frame.
 * @param {fpsCallback} callback Callback fired every time the FPS is computed
 * @param {number} [refreshRate=1] Refresh rate which the fps is computed and the callback is fired (0 to compute every frame, not recommended)
 * @returns {function} Returns a function that should be called on every the loop tick
 * @author Victor B - www.vitim.us - github.com/victornpb/fpsMeter
 */
function createFpsMeter(callback, refreshRate = 1) {
    // ...
}

在此输入图片描述 在此输入图片描述


10
@param {function(number):void} myCallback

自2021年起,在VS Code和WebStorm中运行良好


1
但这不是JSDoc官方支持的,是吗?我在jsdoc.app上找不到任何这样的例子。 - oligofren
在 vscode 中确实非常好用 - 是否有此功能支持的完整文档? - Kludge

3
也许我来回答有点晚了...不过这是我的贡献。使用 ES6 我们可以这样做:
```javascript ```
```html

可能我来到这个答案晚了……然而这是我的贡献。使用 ES6,我们可以这样做:

```
    /**
 *
 * @param {import('../clients')} clients  
 */
export default function socketServer(clients) {
io.on('connection', (webClient) => {


    webClient.on('register', (data) => {
      clients.add(data, webClient);
    });
}

 server.listen(8081, function (err) {
    if (err) throw err;
    console.log('listening on port 8081');
  });

)

在“clients”文件夹中,我们有一个名为index.js的文件,其中包含以下代码。
let clients = new Map();

/**
 * Add Client to Collection
 * @param {string} key
 * @param {object} client
 */
export function add(key, client) {
  clients.set(key, client);
}
/**
 * Remove Client from Collection
 * @param {string} key
 */
export function remove(key) {
  clients.delete(key);
}

export const size = () => clients.size;

因此,在文件/clients/index.js中导出的所有函数都可以作为JsDOC使用,并且您可以通过IntelliSense引用它们。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接