Wat is de juiste manier om callbacks met jsdoc te documenteren?

Ik heb een hele tijd op internet gezocht naar de beste manier om callbacks goed te documenteren met jsdoc, maar helaas heb ik nog geen goede gevonden.

Dit is mijn vraag:

Ik schrijf een Node.js-bibliotheek voor ontwikkelaars. Deze bibliotheek biedt meerdere klassen, functies en methoden waarmee ontwikkelaars zullen werken.

Om mijn code duidelijk en begrijpelijk te maken en om (hopelijk) in de toekomst automatisch wat API-documentatie te genereren, ben ik begonnen met het gebruik van jsdocin mijn code om zelf te documenteren wat er gebeurt.

Stel dat ik een functie definieer zoals de volgende:

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

Met behulp van jsdoc documenteer ik deze functie momenteel als volgt:

/**
  * 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);
});

Ik heb het gevoel dat de bovenstaande oplossing nogal hack-achtig is, aangezien ik niet in absolute termen kan specificeren wat de callback-functie zou moeten accepteren.

Idealiter zou ik iets willen doen als:

/**
  * 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);
});

Het bovenstaande lijkt me in staat te stellen om eenvoudiger over te brengen wat mijn terugbelverzoek moet accepteren. Klopt dat?

Ik denk dat mijn vraag eenvoudig is: wat is de beste manier om mijn callback-functies duidelijk te documenteren met jsdoc?

Bedankt voor uw tijd.


Antwoord 1, autoriteit 100%

JSDoc 3 heeft precies voor dit doel een @callback-tag. Hier is een gebruiksvoorbeeld:

/**
 * 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);
}

Antwoord 2, autoriteit 43%

Een andere mogelijkheid is om de waarde die aan de callback is doorgegeven als volgt te beschrijven:

/**
  * 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);
});

Gebruik @param {function(int):string}om het retourtype van de callback te documenteren.


Antwoord 3, autoriteit 8%

Tussenoplossing om VSCode het te laten begrijpen

/**
 * @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) {
    // ...
}

voer hier de afbeeldingsbeschrijving in
voer hier de afbeeldingsbeschrijving in


Antwoord 4, autoriteit 3%

@param {function(number):void} myCallback

Werkt goed in VS Code en WebStorm vanaf 2021


Antwoord 5, autoriteit 2%

Misschien kom ik te laat met dit antwoord… maar dit is mijn bijdrage. Met ES6 kunnen we dit doen:

   /**
 *
 * @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');
  });
)

In de map ‘clients’ hebben we een index.js-bestand met deze code

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;

Dus alle functies die worden geëxporteerd in bestand /clients/index.js zijn beschikbaar als JsDOC en u kunt ernaar verwijzen via IntelliSense

Other episodes