Repository: discordjs/discord.js
File: packages/core/src/client.ts (TypeScript)

Code before:
	/**
	 * Requests guild members from the gateway and returns an async iterator that yields the data from each guild members chunk event.
	 *
	 * @see {@link https://discord.com/developers/docs/topics/gateway-events#request-guild-members}
	 * @param options - The options for the request
	 * @param timeout - The timeout for waiting for each guild members chunk event
	 * @example
	 * Requesting all members from a guild
	 * ```ts
	 * for await (const { members } of client.requestGuildMembersIterator({ guild_id: '1234567890', query: '', limit: 0 })) {
	 * 	console.log(members);
	 * }
	 * ```
	 */
	public async *requestGuildMembersIterator(options: GatewayRequestGuildMembersData, timeout = 10_000) {
		const shardId = calculateShardId(options.guild_id, await this.gateway.getShardCount());
		const nonce = options.nonce ?? DiscordSnowflake.generate().toString();

		const controller = new AbortController();

		let timer: NodeJS.Timeout | undefined = createTimer(controller, timeout);

		const onRatelimit = (payload: GatewayDispatchPayload) => {
			// We could verify meta.guild_id === options.guild_id as well, but really, the nonce check is enough
			if (payload.t === GatewayDispatchEvents.RateLimited && payload.d.meta.nonce === nonce) {
				controller.abort(new GatewayRateLimitError(payload.d));
			}
		};

		const cleanup = () => {
			if (timer) {
				clearTimeout(timer);
			}

			this.gateway.off(WebSocketShardEvents.Dispatch, onRatelimit);
		};

		this.gateway.on(WebSocketShardEvents.Dispatch, onRatelimit);
		await this.gateway.send(shardId, {
			op: GatewayOpcodes.RequestGuildMembers,
			// eslint-disable-next-line id-length
			d: {
				...options,
				nonce,
			},
		});

		try {
			const iterator = AsyncEventEmitter.on(this, GatewayDispatchEvents.GuildMembersChunk, {
				signal: controller.signal,
			});

Review comment (suggestion):
One thing I'd like to see is what our request payload is. We do this with `DiscordAPIError`:

https://github.com/discordjs/discord.js/blob/5fa92a1ea90c6e83e6a49bc29bf89ee9f61f6d60/packages/rest/src/lib/errors/DiscordAPIError.ts#L66

So that would mean adding another parameter that exposes the data we sent, which would be `d` below (`{ ...options, nonce }`).

If you do agree with this, then I could argue further and say it could be added to @discordjs/ws so #11252 could make use of it too.

Code after:
	/**
	 * Requests guild members from the gateway and returns an async iterator that yields the data from each guild members chunk event.
	 *
	 * @see {@link https://discord.com/developers/docs/topics/gateway-events#request-guild-members}
	 * @param options - The options for the request
	 * @param timeout - The timeout for waiting for each guild members chunk event
	 * @example
	 * Requesting all members from a guild
	 * ```ts
	 * for await (const { members } of client.requestGuildMembersIterator({ guild_id: '1234567890', query: '', limit: 0 })) {
	 * 	console.log(members);
	 * }
	 * ```
	 */
	public async *requestGuildMembersIterator(options: GatewayRequestGuildMembersData, timeout = 10_000) {
		const shardId = calculateShardId(options.guild_id, await this.gateway.getShardCount());
		const nonce = options.nonce ?? DiscordSnowflake.generate().toString();

		const controller = new AbortController();

		let timer: NodeJS.Timeout | undefined = createTimer(controller, timeout);

		const onRatelimit = ({ data }: ToEventProps<GatewayRateLimitedDispatchData>) => {
			// We could verify meta.guild_id === options.guild_id as well, but really, the nonce check is enough
			if (data.meta.nonce === nonce) {
				controller.abort(new GatewayRateLimitError(data, options));
			}
		};

		const cleanup = () => {
			if (timer) {
				clearTimeout(timer);
			}

			this.off(GatewayDispatchEvents.RateLimited, onRatelimit);
		};

		this.on(GatewayDispatchEvents.RateLimited, onRatelimit);
		await this.gateway.send(shardId, {
			op: GatewayOpcodes.RequestGuildMembers,
			// eslint-disable-next-line id-length
			d: {
				...options,
				nonce,
			},
		});

		try {
			const iterator = AsyncEventEmitter.on(this, GatewayDispatchEvents.GuildMembersChunk, {
				signal: controller.signal,
			});