Daniel
Daniel

Reputation: 97

Alternative to sending a lot of requests to server side

I got cart products at my eCommerce website that I built with Angular,NodeJS,MongoDB. When my client wants to add quantity or decrease quantity of product for example from 4 to 2, it will send 2 patch requests to update the quantity (first one from 4 to 3 and second from 3 to 2), I want it to make a way better algorithm that will do in 1 request (for example at the end of the session, when the user is leaving the website, etc..) I tried using Navigator.sendBeacon and it sometimes works and sometimes not (which I can't use, I need something that works all the time..) I don't want to show the user any message before he leaves which I know that make the fix for that issue and it will work with navigator.sendBeacon Here is what I made with navigator.sendBeacon :

Client Side:

  @HostListener('window:beforeunload', ['$event'])
  onBeforeUnload(): void {
    const data = new FormData();
    data.append('cartProducts', JSON.stringify(this.cartProducts));
    navigator.sendBeacon("http://localhost:3000/api/shopping-online/get-beacon", data)
  }

  public cartProducts: CartItem[] = [];

Cart products gets the array of objects from the database.

Server Side:

    router.post("/get-beacon", async (request, response) => {
  try {
    console.log("hi");
  }
  catch (err) {
    console.log("bye");
  }
})

Sometimes I get the "hi" message on NodeJS terminal and sometimes it comes in delay of few seconds and sometimes it doesn't come at all.

I will glad for any idea with navigator.sendBeacon or any other idea you got to stop that bad algorithm that every click on change quantity it sends to server side (can be even 10 clicks in a row which is very bad).

Upvotes: 2

Views: 754

Answers (2)

Daniel
Daniel

Reputation: 97

With a great advice of Alan got to exactly what I wanted, here is the solution. Btw there is no mention how to get exactly the sendBeacon on NodeJS so I will add all the way here.

Client Side (Angular):

  @HostListener('document:visibilitychange', ['$event'])
  visibilitychange() {
    if (this.cartProducts && this.isCartProductsChanged) {
      const blob = new Blob([JSON.stringify(this.cartProducts)], { type: 'application/json' });
      navigator.sendBeacon("http://localhost:3000/api/shopping-online/get-beacon", blob)
      this.isCartProductsChanged = false;
    }
  }

  public cartProducts: CartItem[] = [];
  public isCartProductsChanged: boolean = false;

It will send the beacon only if there are products in cart, only if any changes made to the cart (added quantity or product)

Server side (NodeJS):

On controller:

router.post("/get-beacon", async (request, response) => {
  try {
    console.log(request.body);
  }
  catch (err) {
    console.log("bye");
  }
})

On app.js

const shoppingController = require("./controllers/shopping-controller");
const express = require("express");
const server = express();
const cors = require("cors");
server.use(function (req, res, next) {
  res.header("Access-Control-Allow-Credentials", "true");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content- 
    Type, Accept");
  next();
});
 server.use(express.text());
 let port = process.env.PORT || 3000;
 server.use("/api/shopping-online", shoppingController);
 server.listen(port, () => console.log(`Listening on 
    http://localhost:${port}`));

The usage instead of body parser since express version 4.16.0 to make it work is

server.use(express.text());

Before express version 4.16.0 you have to install body-parser

 npm i body-parser

And add at app.js:

const bodyParser = require("body-parser");
server.use(bodyParser.text());

Upvotes: 0

Alan Friedman
Alan Friedman

Reputation: 1610

Have you tried listening for visibilitychange instead of using onBeforeUnload?

document.addEventListener('visibilitychange', () => {
  if (document.visibilityState === 'hidden') {
    const data = new FormData();
    data.append('cartProducts', JSON.stringify(this.cartProducts));
    navigator.sendBeacon("http://localhost:3000/api/shopping-online/get-beacon", data);
  }
});

MDN docs

Upvotes: 1

Related Questions