Skip to content

Instantly share code, notes, and snippets.

@harmony7
Last active May 7, 2020 06:40
Show Gist options
  • Save harmony7/0a443948d265c1a18f74dd8a0be0e61c to your computer and use it in GitHub Desktop.
Save harmony7/0a443948d265c1a18f74dd8a0be0e61c to your computer and use it in GitHub Desktop.
Streaming demo with fetch

The following is a demo that uses the fetch API in a browser to subscribe to messages streamed through a GRIP Stream pushed through a sample server that is proxied behind the open-source Pushpin (https://pushpin.org/) server.

To run the demo:

  1. Clone the js-grip repository, then build the commonjs build.
git clone https://github.com/fanout/js-grip
cd js-grip
npm install
npm run build-commonjs
  1. Start the server process. This runs on localhost:3000.
node demo/server
  1. Install Pushpin (see https://pushpin.org/docs/install/)
  2. Make sure Pushpin points to localhost:3000. routes file:
* localhost:3000
  1. Start Pushpin.
pushpin

This will start a GRIP proxy running on port 7999. A streaming API will be available at http://localhost:7999/stream. The API simply holds open a GRIP stream on the channel test.

  1. Create an HTML file with the following content. Make adjustments as necessary if you are using a browser that does not support fetch or async/await natively.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Pushpin Fetch Demo</title>
</head>
<body>

    <h1>Pushpin Fetch Demo</h1>

    <div>
        <button id="button" type="button">Go</button>
    </div>

    <div>
        <pre id="output" style="color: white; background: black;"></pre>
    </div>

    <script>
        let reader = null;

        const button = document.getElementById('button');
        button.addEventListener('click', async () => {

            if (reader == null) {
                // We are not streaming yet.

                // We disable the button while we start the fetch
                button.disabled = true;

                try {
                    console.log("Fetching.");
                    const res = await fetch('http://localhost:7999/stream');
                    reader = res.body.getReader();
                } catch(ex) {
                    console.log("Fetch error.");
                    reader = null;
                } finally {
                    button.disabled = false;
                }

                // If we failed at obtaining a reader then we bail out.
                if (reader == null) {
                    return;
                }

                // We are now streaming.
                console.log("Streaming...");
                button.innerText = 'Cancel';

                // Use the ReadableStream interface to read from the
                // response until the stream closes.
                let total = 0;
                while (true) {
                    const { done, value } = await reader.read();

                    if (done) {
                        // Finished Streaming
                        break;
                    }

                    total += value.length;
                    console.log(total + " bytes so far...");

                    document.getElementById('output').textContent +=
                        new TextDecoder("utf-8").decode(value);
                }

                console.log("Finished Streaming.");
                console.log("Read a total of " + total + " bytes.");

                reader = null;
                button.innerText = 'Go';

            } else {

                // If we are already streaming, cancel.
                // This will cause the read promise above to resolve with
                // a true value for "done", exiting the while loop.
                reader.cancel();
                reader = null;

            }
        });

    </script>
</body>
</html>
  1. Open the HTML file in a web browser. You will see a button labeled Go. Click this button. The browser will use fetch to connect to the streaming API at http://localhost:7999/stream.

  2. In another terminal window, run the publish demo file.

cd js-grip
node demo/publish test "Message"

This pushes a message Message to the channel test.

  1. In the web browser window you opened in step 7, you should see the test message.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment