"undefined" response from getJSON() with Transit app API

Does anyone know how to get a JSON from the Transit app? I am trying to get my getJSON() method to work correctly for obtaining stops (will implement code for routes later) near a location.

So far, here is what I got for my backend (transit-data.web.js):

/************
.web.js file
************

Backend '.web.js' files contain functions that run on the server side and can be called from page code.

Learn more at https://dev.wix.com/docs/develop-websites/articles/coding-with-velo/backend-code/web-modules/calling-backend-code-from-the-frontend

****/

/**** Call the sample multiply function below by pasting the following into your page code:

import { multiply } from 'backend/new-module.web';

$w.onReady(async function () {
   console.log(await multiply(4,5));
});

****/

import { Permissions, webMethod } from "wix-web-module";
import { getJSON } from 'wix-fetch';
import { getSecret } from 'wix-secrets-backend'

export const multiply = webMethod(
    Permissions.Anyone,
    (factor1, factor2) => {
        return factor1 * factor2
    }
);

export const getStopsNearLocation = webMethod(Permissions.Anyone, async (lat, lon, max_distance = 150, stop_filter = "All", pickup_dropoff_filter = "Everything") => {
    const apiKey = await getSecret('transit_app');
    const parameters = {
        lat: lat,
        lon: lon,
        max_distance: max_distance,
        stop_filter: stop_filter,
        pickup_dropoff_filter: pickup_dropoff_filter,
    }
    const query = new URLSearchParams(parameters).toString();
    const url = "https://external.transitapp.com/v3/public/nearby_stops";
    const fullURL = `${url}?${query}`;
    const options = {
        headers: { apiKey: apiKey }
    }
    getJSON(fullURL, options).then((response) => {
        if (response.ok) {
            return response.json();
        } else {
            throw new Error(`Error with "${fullURL}": ${response.status} (${response.url}) - ${response.statusText}`);
        }
    }).catch((error) => { console.log(error) });
})

Here is what I got for the front-end:

// Velo API Reference: https://www.wix.com/velo/reference/api-overview/introduction

$w.onReady(function () {

// Write your Javascript code here using the Velo framework API

// Print hello world:

// console.log("Hello world!");

// Call functions on page elements, e.g.:

// $w("#button1").label = "Click me!";

// Click "Run", or Preview your site, to execute your code

});

/**** Call the sample multiply function below by pasting the following into your page code:

*****/

import wixData from 'wix-data';

//import { getNearbyStops, getNearbyRoutes } from 'backend/transit-module.web.js';

import { getStopsNearLocation } from 'backend/transit-data.web.js'

$w.onReady(async function () {

wixData.truncate("Transit");

let retrievedStops = await getStopsNearLocation(49.2526028832592, -123.00380973189016, 1500) //getNearbyStops(49.2526028832592, -123.00380973189016);

//let retrievedRoutes = await //getNearbyRoutes(49.2526028832592, -123.00380973189016);

console.log(retrievedStops);

//console.log(retrievedRoutes);

wixData.bulkInsert("Transit", retrievedStops);

if($w('#dataset1').getTotalCount() > 0){

$w('#Section3Regular').show();

}

});

/*

****/

Basically, I get this in my console:

undefined

Error with "https://external.transitapp.com/v3/public/nearby_stops?lat=49.2526028832592&lon=-123.00380973189016&max_distance=1500&stop_filter=All&pickup_dropoff_filter=Everything": undefined (undefined) - undefined

With Verbose enabled:

[datasetReady event] triggered on wix-dataset

undefined

[wix-dataset.getTotalCount] called

[wix-dataset.getTotalCount] returned with ( 0 )

Error with "https://external.transitapp.com/v3/public/nearby_stops?lat=49.2526028832592&lon=-123.00380973189016&max_distance=1500&stop_filter=All&pickup_dropoff_filter=Everything": undefined (undefined) - undefined

I am not fully sure what went wrong and how to resolve it.

Hi, Jeremy_Leung!!
Please rewrite your code like this.

(before)

    getJSON(fullURL, options).then((response) => {
        if (response.ok) {
            return response.json();
        } else {
            throw new Error(`Error with "${fullURL}": ${response.status} (${response.url}) - ${response.statusText}`);
        }
    }).catch((error) => { console.log(error) });

(after)

    getJSON(fullURL, options).then(async(response) => { // here!!
        if (response.ok) {
            return await response.json(); // here!!
        } else {
            throw new Error(`Error with "${fullURL}": ${response.status} (${response.url}) - ${response.statusText}`);
        }
    }).catch((error) => { console.log(error) });

Sorry, applied the changes and still getting it:

[datasetReady event] triggered on wix-dataset

undefined

[wix-dataset.getTotalCount] called

[wix-dataset.getTotalCount] returned with ( 0 )

Error with "https://external.transitapp.com/v3/public/nearby_stops?lat=49.2526028832592&lon=-123.00380973189016&max_distance=1500&stop_filter=All&pickup_dropoff_filter=Everything": undefined (undefined) - undefined

Have you tried using fetch instead of getJSON?

Used fetch() in the past.

Previous backend version:

/************
.web.js file
************

Backend '.web.js' files contain functions that run on the server side and can be called from page code.

Learn more at https://dev.wix.com/docs/develop-websites/articles/coding-with-velo/backend-code/web-modules/calling-backend-code-from-the-frontend

****/

/**** Call the sample multiply function below by pasting the following into your page code:

import { multiply } from 'backend/new-module.web';

$w.onReady(async function () {
   console.log(await multiply(4,5));
});

****/

import { Permissions, webMethod } from "wix-web-module";
import { fetch } from "wix-fetch";
import { getSecret } from "wix-secrets-backend";

//...

const transit_api_link = "https://external.transitapp.com/v3/public/";

export const multiply = webMethod(
    Permissions.Anyone,
    (factor1, factor2) => {
        return factor1 * factor2
    }
);

// GET call using fetch because nearby Stops is a get request - though has a POST body example just in case that helps for future stuff. 

export const getNearbyRoutes = webMethod(

    Permissions.Anyone,

    async (latitude, longitude, radius = 1500, isRealTime = false) => {

        const transitAppApiKey = await getSecret("transit_app");

        // Used for POST requests, not for Gets - see below for the GET linking.
        const jsonBody = {
            lat: latitude,
            lon: longitude,
            max_distance: radius, // Presumably the zoom level of the Google Maps that's on the page, though don't recall exaclty how to get information from it.
            should_update_realtime: isRealTime // The default value for the API, it seems like, for getting the stops

        };

        const fetchOptions = {

            method: "get",

            headers: { "Content-Type": "application/json", "apiKey": transitAppApiKey },

            //body: JSON.stringify(jsonBody),

        };

        console.log("Sending data: " + JSON.stringify(jsonBody));

        const response = await fetch(

            transit_api_link + "nearby_routes?lat=" + latitude + "'&lon=" + longitude + "&maxDistance=" + radius + "&should_update_realtime=" + isRealTime,

            fetchOptions,

        );

        return response.json();

    },

);

// GET call using fetch because nearby Stops is a get request - though has a POST body example just in case that helps for future stuff. 

export const getNearbyStops = webMethod(

    Permissions.Anyone,

    async (latitude, longitude, radius = 1500, stopType = "All", riderFilter = "Everything") => {

        const transitAppApiKey = await getSecret("transit_app");

        // Used for POST requests, not for Gets - see below for the GET linking.
        const jsonBody = {
            lat: latitude,
            lon: longitude,
            max_distance: radius, // Presumably the zoom level of the Google Maps that's on the page, though don't recall exaclty how to get information from it.

            stop_filter: stopType, // The default value for the API, it seems like, for getting the stops
            pickup_dropoff_filter: riderFilter

        };

        const fetchOptions = {

            method: "get",

            headers: { "Content-Type": "application/json", "apiKey": transitAppApiKey },

            //body: JSON.stringify(jsonBody),

        };

        console.log("Sending data: " + JSON.stringify(jsonBody));

        const response = await fetch(

            transit_api_link + "nearby_stops?lat=" + latitude + "'&lon=" + longitude + "&maxDistance=" + radius + "&stop_filter=" + riderFilter + "&pickup_dropoff_filter" + riderFilter,

            fetchOptions,

        );

        return response.json();

    },

);

Frontend with previous methods used:

// Velo API Reference: https://www.wix.com/velo/reference/api-overview/introduction

$w.onReady(function () {

// Write your Javascript code here using the Velo framework API

// Print hello world:

// console.log("Hello world!");

// Call functions on page elements, e.g.:

// $w("#button1").label = "Click me!";

// Click "Run", or Preview your site, to execute your code

});

/**** Call the sample multiply function below by pasting the following into your page code:

*****/

import wixData from 'wix-data';

import { getNearbyStops, getNearbyRoutes } from 'backend/transit-module.web.js';

import { getStopsNearLocation } from 'backend/transit-data.web.js'

$w.onReady(async function () {

wixData.truncate("Transit");

let retrievedStops = await /*getStopsNearLocation(49.2526028832592, -123.00380973189016, 1500)*/ getNearbyStops(49.2526028832592, -123.00380973189016);

//let retrievedRoutes = await //getNearbyRoutes(49.2526028832592, -123.00380973189016);

console.log(retrievedStops);

//console.log(retrievedRoutes);

wixData.bulkInsert("Transit", retrievedStops);

if($w('#dataset1').getTotalCount() > 0){

$w('#Section3Regular').show();

}

});

/*

****/

This is what I get in the console:

Sending data: {"lat":49.2526028832592,"lon":-123.00380973189016,"max_distance":1500,"stop_filter":"All","pickup_dropoff_filter":"Everything"}

{...}

stops: Array(0)

With Verbose enabled:

[datasetReady event] triggered on wix-dataset

Sending data: {"lat":49.2526028832592,"lon":-123.00380973189016,"max_distance":1500,"stop_filter":"All","pickup_dropoff_filter":"Everything"}

{...}
stops: Array(0)

[wix-dataset.getTotalCount] called

[wix-dataset.getTotalCount] returned with ( 0 )

Using the coordinates on Google Maps, there are supposed to be bus stops within 1500 m. As you see what I got in the console, I got no results. I thought about simplifying the backend with using getJSON() in my revision since I am only getting data from the Transit app via HTTPS.

Just tried out an idea I currently have in mind which is emulating the example in the Wix dev doc article about getJSON():

import { getJSON } from "wix-fetch";

// ...

getJSON("https://someapi.com/api/someendpoint")
  .then((json) => console.log(json.someKey))
  .catch((err) => console.log(err));

Idea variant 1:

/************
.web.js file
************

Backend '.web.js' files contain functions that run on the server side and can be called from page code.

Learn more at https://dev.wix.com/docs/develop-websites/articles/coding-with-velo/backend-code/web-modules/calling-backend-code-from-the-frontend

****/

/**** Call the sample multiply function below by pasting the following into your page code:

import { multiply } from 'backend/new-module.web';

$w.onReady(async function () {
   console.log(await multiply(4,5));
});

****/

import { Permissions, webMethod } from "wix-web-module";
import { getJSON } from 'wix-fetch';
import { getSecret } from 'wix-secrets-backend'

export const multiply = webMethod(
    Permissions.Anyone,
    (factor1, factor2) => {
        return factor1 * factor2
    }
);

export const getStopsNearLocation = webMethod(Permissions.Anyone, async (lat, lon, max_distance = 150, stop_filter = "All", pickup_dropoff_filter = "Everything") => {
    const apiKey = await getSecret('transit_app');
    const parameters = {
        lat: lat,
        lon: lon,
        max_distance: max_distance,
        stop_filter: stop_filter,
        pickup_dropoff_filter: pickup_dropoff_filter,
    }
    const query = new URLSearchParams(parameters).toString();
    const url = "https://external.transitapp.com/v3/public/nearby_stops";
    const fullURL = `${url}?${query}`;
    const options = {
        headers: { apiKey: apiKey }
    }
    getJSON(fullURL, options).then(/*async*/(json/*response*/) => {
        /*if (response.ok) {
            return await response.json();
        } else {
            throw new Error(`Error with "${fullURL}": ${response.status} (${response.url}) - ${response.statusText}`);
        }*/
        return json.json();
    }).catch((error) => { console.log(error) });
})

Variant 1 console result:

[datasetReady event] triggered on wix-dataset

undefined

[wix-dataset.getTotalCount] called

[wix-dataset.getTotalCount] returned with ( 0 )

json.json is not a function

Idea variant 2:

/************
.web.js file
************

Backend '.web.js' files contain functions that run on the server side and can be called from page code.

Learn more at https://dev.wix.com/docs/develop-websites/articles/coding-with-velo/backend-code/web-modules/calling-backend-code-from-the-frontend

****/

/**** Call the sample multiply function below by pasting the following into your page code:

import { multiply } from 'backend/new-module.web';

$w.onReady(async function () {
   console.log(await multiply(4,5));
});

****/

import { Permissions, webMethod } from "wix-web-module";
import { getJSON } from 'wix-fetch';
import { getSecret } from 'wix-secrets-backend'

export const multiply = webMethod(
    Permissions.Anyone,
    (factor1, factor2) => {
        return factor1 * factor2
    }
);

export const getStopsNearLocation = webMethod(Permissions.Anyone, async (lat, lon, max_distance = 150, stop_filter = "All", pickup_dropoff_filter = "Everything") => {
    const apiKey = await getSecret('transit_app');
    const parameters = {
        lat: lat,
        lon: lon,
        max_distance: max_distance,
        stop_filter: stop_filter,
        pickup_dropoff_filter: pickup_dropoff_filter,
    }
    const query = new URLSearchParams(parameters).toString();
    const url = "https://external.transitapp.com/v3/public/nearby_stops";
    const fullURL = `${url}?${query}`;
    const options = {
        headers: { apiKey: apiKey }
    }
    getJSON(fullURL, options).then(/*async*/(json/*response*/) => {
        /*if (response.ok) {
            return await response.json();
        } else {
            throw new Error(`Error with "${fullURL}": ${response.status} (${response.url}) - ${response.statusText}`);
        }*/
        return json;
    }).catch((error) => { console.log(error) });
})

Variant 2 console result:

[datasetReady event] triggered on wix-dataset

undefined

[wix-dataset.getTotalCount] called

[wix-dataset.getTotalCount] returned with ( 0 )

Hi, LPRFelica! I’m back. Then, I see. Please start again from the initial code. Whether you use getJSON or fetch doesn’t matter, but I just realized your code is missing a crucial element. Your code lacks a return statement to send the response obtained in the backend back to the frontend.

↓ here!!
return getJSON(fullURL, options).then(async(response) => { // here!!
        if (response.ok) {
            return await response.json(); // here!!
        } else {
            throw new Error(`Error with "${fullURL}": ${response.status} (${response.url}) - ${response.statusText}`);
        }
    }).catch((error) => { console.log(error) });

Ah, just modified the code and unfortunately, console result is still the same:

[datasetReady event] triggered on wix-dataset

undefined

Error with "https://external.transitapp.com/v3/public/nearby_stops?lat=49.2526028832592&lon=-123.00380973189016&max_distance=1500&stop_filter=All&pickup_dropoff_filter=Everything": undefined (undefined) - undefined

[wix-dataset.getTotalCount] called

[wix-dataset.getTotalCount] returned with ( 0 )

I understand. How about starting with the simplest scenario to see if you can get results? It’s important to identify issues one by one. Therefore, I suggest commenting out the dataset-related code for now. Focus on rewriting the code to only handle fetching responses from the API and returning them to the frontend. Also, it might be necessary to check if the API key is correct. Consider hardcoding the API key into your code for testing purposes (of course, don’t paste that code here). Try using values for lat and lon from the Transit API example, such as lat=45.526168077787894 and lon=-73.59506067289408. This way, you can confirm what is working correctly and gradually pinpoint where the issue might be.

I just further modified my code for then() and I finally got transit stops result at last!

Here is what I modified my backend to:

/************
.web.js file
************

Backend '.web.js' files contain functions that run on the server side and can be called from page code.

Learn more at https://dev.wix.com/docs/develop-websites/articles/coding-with-velo/backend-code/web-modules/calling-backend-code-from-the-frontend

****/

/**** Call the sample multiply function below by pasting the following into your page code:

import { multiply } from 'backend/new-module.web';

$w.onReady(async function () {
   console.log(await multiply(4,5));
});

****/

import { Permissions, webMethod } from "wix-web-module";
import { getJSON } from 'wix-fetch';
import { getSecret } from 'wix-secrets-backend'

export const multiply = webMethod(
    Permissions.Anyone,
    (factor1, factor2) => {
        return factor1 * factor2
    }
);

export const getStopsNearLocation = webMethod(Permissions.Anyone, async (lat, lon, max_distance = 150, stop_filter = "All", pickup_dropoff_filter = "Everything") => {
    const apiKey = await getSecret('transit_app');
    const parameters = {
        lat: lat,
        lon: lon,
        max_distance: max_distance,
        stop_filter: stop_filter,
        pickup_dropoff_filter: pickup_dropoff_filter,
    }
    const query = new URLSearchParams(parameters).toString();
    const url = "https://external.transitapp.com/v3/public/nearby_stops";
    const fullURL = `${url}?${query}`;
    const options = {
        headers: { apiKey: apiKey }
    }
    return getJSON(fullURL, options).then(/*async*/(/*response*/json) => {
        /*if (response.ok) {
            return await response.json();
        } else {
            throw new Error(`Error with "${fullURL}": ${response.status} (${response.url}) - ${response.statusText}`);
        }*/
        return json;
    }).catch((error) => { console.log(error) });
})

Here is what I got in the console:

[datasetReady event] triggered on wix-dataset

{...}

stops: [...]
[wix-dataset.getTotalCount] called

[wix-dataset.getTotalCount] returned with ( 0 )

Here is a newly modified frontend:

// Velo API Reference: https://www.wix.com/velo/reference/api-overview/introduction

$w.onReady(function () {

// Write your Javascript code here using the Velo framework API

// Print hello world:

// console.log("Hello world!");

// Call functions on page elements, e.g.:

// $w("#button1").label = "Click me!";

// Click "Run", or Preview your site, to execute your code

});

/**** Call the sample multiply function below by pasting the following into your page code:

*****/

import wixData from 'wix-data';

import { getStopsNearLocation } from 'backend/transit-data.web.js'

$w.onReady(async function () {

wixData.truncate("Transit");

let retrievedStops = await getStopsNearLocation(49.2526028832592, -123.00380973189016)

console.log(retrievedStops);

wixData.bulkInsert("Transit", retrievedStops);

if($w('#dataset1').getTotalCount() > 0){

$w('#Section3Regular').show();

}

});

/*

****/

Here is the console result for the new revision:

[datasetReady event] triggered on wix-dataset

{...}

stops: [...]

[wix-dataset.getTotalCount] called

[wix-dataset.getTotalCount] returned with ( 0 )

Here is the JSON data for the new revision:

{
  "stops": [
    {
      "distance": 125,
      "global_stop_id": "TSL:72260",
      "location_type": 0,
      "parent_station_global_stop_id": "null",
      "route_type": 3,
      "rt_stop_id": "1554",
      "stop_code": "51542",
      "stop_lat": 49.25149401014873,
      "stop_lon": -123.004152179296,
      "stop_name": "Willingdon Ave / Goard Way Northbound",
      "wheelchair_boarding": 1
    },
    {
      "distance": 137,
      "global_stop_id": "TSL:72323",
      "location_type": 0,
      "parent_station_global_stop_id": "null",
      "route_type": 3,
      "rt_stop_id": "1558",
      "stop_code": "51546",
      "stop_lat": 49.2514400509286,
      "stop_lon": -123.0044759346168,
      "stop_name": "Willingdon Ave / Goard Way Southbound",
      "wheelchair_boarding": 1
    }
  ]
}

Anyway, thanks for helping out!

1 Like

I’m glad I could contribute to the solution!!! :grin: yeah!

2 Likes

Glad you got things working @LPRFeliCa!

And thanks for all the help you provided @onemoretime :purple_heart:

1 Like