TypeScript definitions for Phoenix JavaScript client library enabling real-time WebSocket communication with Phoenix Framework applications
Push mechanism for sending messages to channels with delivery status tracking and timeout handling, enabling reliable message delivery confirmation.
Creates a new Push instance for sending messages with status tracking.
/**
* Creates a new Push instance for sending messages with status tracking
* @param channel - Channel to send message through
* @param event - Event name for the message
* @param payload - Message payload object
* @param timeout - Timeout in milliseconds for the push operation
*/
constructor(channel: Channel, event: string, payload: object, timeout: number);Note: Push instances are typically created through channel.push() rather than directly constructing them.
Send and resend push messages.
/**
* Send the push message
*/
send(): void;
/**
* Resend the push message with a new timeout
* @param timeout - New timeout value in milliseconds
*/
resend(timeout: number): void;Usage Example:
import { Channel, Socket } from "phoenix";
const socket = new Socket("/socket");
const channel = socket.channel("room:lobby");
// Create push through channel (recommended)
const push = channel.push("new_message", {
body: "Hello, Phoenix!",
user_id: 123
}, 5000);
// Send immediately (usually not needed as channel.push() sends automatically)
push.send();
// Resend with longer timeout if needed
push.resend(10000);Register callbacks for different push response statuses.
/**
* Register callback for specific push status
* @param status - Push status to handle ("ok", "error", or "timeout")
* @param callback - Function to call when status is received
* @returns Push instance for chaining
*/
receive(status: PushStatus, callback: (response?: any) => any): this;
type PushStatus = "ok" | "error" | "timeout";Usage Example:
// Chain status handlers
channel.push("create_post", {
title: "My Post",
content: "Post content here..."
})
.receive("ok", (response) => {
console.log("Post created successfully:", response.post);
// Navigate to new post
window.location.href = `/posts/${response.post.id}`;
})
.receive("error", (errors) => {
console.error("Failed to create post:", errors);
// Show validation errors to user
displayErrors(errors);
})
.receive("timeout", () => {
console.warn("Post creation timed out");
// Show retry option to user
showRetryDialog();
});function sendMessageWithRetry(channel: Channel, event: string, payload: object, maxRetries = 3) {
let attempts = 0;
function attempt(): Promise<any> {
return new Promise((resolve, reject) => {
attempts++;
channel.push(event, payload, 5000)
.receive("ok", resolve)
.receive("error", (errors) => {
if (attempts < maxRetries) {
console.log(`Attempt ${attempts} failed, retrying...`);
setTimeout(() => {
attempt().then(resolve).catch(reject);
}, 1000 * attempts); // Exponential backoff
} else {
reject(new Error(`Failed after ${maxRetries} attempts: ${JSON.stringify(errors)}`));
}
})
.receive("timeout", () => {
if (attempts < maxRetries) {
console.log(`Attempt ${attempts} timed out, retrying...`);
setTimeout(() => {
attempt().then(resolve).catch(reject);
}, 1000 * attempts);
} else {
reject(new Error(`Timed out after ${maxRetries} attempts`));
}
});
});
}
return attempt();
}
// Usage
sendMessageWithRetry(channel, "important_action", { data: "critical" })
.then(result => console.log("Success:", result))
.catch(error => console.error("Final failure:", error));function handleFormSubmission(channel: Channel, formData: object) {
const submitButton = document.getElementById("submit-btn") as HTMLButtonElement;
const errorDiv = document.getElementById("errors") as HTMLDivElement;
const successDiv = document.getElementById("success") as HTMLDivElement;
// Disable submit button during request
submitButton.disabled = true;
submitButton.textContent = "Submitting...";
channel.push("form_submit", formData, 10000)
.receive("ok", (response) => {
// Success handling
successDiv.style.display = "block";
successDiv.textContent = "Form submitted successfully!";
errorDiv.style.display = "none";
// Reset form
(document.getElementById("form") as HTMLFormElement).reset();
})
.receive("error", (errors) => {
// Error handling
errorDiv.style.display = "block";
errorDiv.innerHTML = "";
// Display validation errors
Object.entries(errors).forEach(([field, messages]) => {
const errorItem = document.createElement("div");
errorItem.textContent = `${field}: ${(messages as string[]).join(", ")}`;
errorDiv.appendChild(errorItem);
});
successDiv.style.display = "none";
})
.receive("timeout", () => {
// Timeout handling
errorDiv.style.display = "block";
errorDiv.textContent = "Request timed out. Please try again.";
successDiv.style.display = "none";
});
// Always re-enable submit button
setTimeout(() => {
submitButton.disabled = false;
submitButton.textContent = "Submit";
}, 1000);
}function pushPromise(channel: Channel, event: string, payload: object, timeout = 5000): Promise<any> {
return new Promise((resolve, reject) => {
channel.push(event, payload, timeout)
.receive("ok", resolve)
.receive("error", reject)
.receive("timeout", () => reject(new Error("Push operation timed out")));
});
}
// Usage with async/await
async function createUser(channel: Channel, userData: object) {
try {
const response = await pushPromise(channel, "create_user", userData, 8000);
console.log("User created:", response.user);
return response.user;
} catch (error) {
console.error("Failed to create user:", error);
throw error;
}
}async function batchOperations(channel: Channel, operations: Array<{event: string, payload: object}>) {
const results = [];
const errors = [];
for (const [index, operation] of operations.entries()) {
try {
const result = await new Promise((resolve, reject) => {
channel.push(operation.event, operation.payload, 5000)
.receive("ok", resolve)
.receive("error", reject)
.receive("timeout", () => reject(new Error("Timeout")));
});
results.push({ index, result });
} catch (error) {
errors.push({ index, error, operation });
}
}
return { results, errors };
}
// Usage
const operations = [
{ event: "create_post", payload: { title: "Post 1" } },
{ event: "create_post", payload: { title: "Post 2" } },
{ event: "update_user", payload: { name: "Updated Name" } }
];
batchOperations(channel, operations)
.then(({ results, errors }) => {
console.log(`Completed ${results.length} operations successfully`);
if (errors.length > 0) {
console.error(`${errors.length} operations failed:`, errors);
}
});class PushMonitor {
private activePushes: Map<string, { push: Push, startTime: number }> = new Map();
track(id: string, channel: Channel, event: string, payload: object, timeout = 5000) {
const startTime = Date.now();
const push = channel.push(event, payload, timeout);
this.activePushes.set(id, { push, startTime });
push
.receive("ok", (response) => {
this.complete(id, "ok", response);
})
.receive("error", (errors) => {
this.complete(id, "error", errors);
})
.receive("timeout", () => {
this.complete(id, "timeout", null);
});
return push;
}
private complete(id: string, status: PushStatus, response: any) {
const entry = this.activePushes.get(id);
if (entry) {
const duration = Date.now() - entry.startTime;
console.log(`Push ${id} completed with status ${status} in ${duration}ms`);
this.activePushes.delete(id);
}
}
getActivePushes(): string[] {
return Array.from(this.activePushes.keys());
}
getActivePushCount(): number {
return this.activePushes.size;
}
}
// Usage
const monitor = new PushMonitor();
monitor.track("post-creation", channel, "create_post", {
title: "My New Post",
content: "Post content..."
});
console.log("Active pushes:", monitor.getActivePushCount());Install with Tessl CLI
npx tessl i tessl/npm-types--phoenix