How can I do JSONP requests from Sveltekit?

127 views Asked by At

We are running a Shopify store, and have come to a point where we need more flexibility content wise. My solution to this is to have content delivered via a custom CMS to a subdomain. One issue I have is getting cart content from the primary domain on Shopify to the Sveltekit solution on the subdomain (I need to show the cart items count in the header, and also a list of the items in the cart in a sidebar).

Unfortunately just fetching the cart.json gives a CORS error. I have found a solution using JSONP:

function getCartData(data){
  /* do something with the data. In this example we are just loggin it */
  console.log(data)
}

var script = document.createElement('script');
script.src = 'https://jasons-experiments.myshopify.com/cart.json?callback=getCartData'
document.getElementsByTagName('head')[0].appendChild(script);

from this site: https://freakdesign.com.au/blogs/news/get-cart-contents-via-jsonp.

I am really stumped on how to do something like this from Sveltekit. Is this even possible?

2

There are 2 answers

0
pusle On BEST ANSWER

Finally figured it out. In a blogpost from Logrocket, they try to explain the workings of JSONP. Probably succeeds as well, perhaps I just need to read it again. Anyway, I exctracted the function in their example and created a component in Svelte called getCartData.js:

let jsonpID = 0;

function jsonp(timeout = 7500) {
  const url = 'https://shopdomain.net/cart.json';
  const head = document.querySelector('head');
  jsonpID += 1;

  return new Promise((resolve, reject) => {
    let script = document.createElement('script');
    const callbackName = `jsonpCallback${jsonpID}`;

    script.src = encodeURI(`${url}?callback=${callbackName}`);
    script.async = true;

    const timeoutId = window.setTimeout(() => {
      cleanUp();

      return reject(new Error('Timeout'));
    }, timeout);

    window[callbackName] = data => {
      cleanUp();

      return resolve(data);
    };

    script.addEventListener('error', error => {
      cleanUp();

      return reject(error);
    });

    function cleanUp() {
      window[callbackName] = undefined;
      head.removeChild(script);
      window.clearTimeout(timeoutId);
      script = null;
    }


    head.appendChild(script);
  });
}

export default jsonp

And in my header component, I just awaited the result:

import jsonp from '$lib/helpers/getCartData';
import { onMount } from 'svelte';

let cartData = jsonp();

onMount(async () => {
    console.log(await cartData);
})
6
David Lazar On

Since you are not doing anything with secrets or API calls, and just want to send JSON to some foreign domain you control, just set your server there to be CORS-friendly and you can then make XHR calls to it without triggering CORS exceptions. Usually this is a very easy mod for you to make to your server.