hcphoon
hcphoon

Reputation: 548

Unexpected end of JSON input error after pending promise

I am in the process of creating a data handler and as part of that I need to download a file to then parse and work with as part of the handler.

I have wrapped the request for the file in a promise and asynchronously called the method from other methods

I have included the handler from a separate test file as follows

let DataHandler = require('./handler');

const handler = new DataHandler();

console.log(handler.getSupervisors());

The getSupervisors method is as follows

async getSupervisors() {
    const parsed = await this.loadFile();
    let supervisorList = [];

    parsed.controllers.map(controller => {
        if (controller.rating === 11 || controller.rating === 12){
            supervisorList.push(controller);
        }
    });

    return supervisorList;
}

This calls the loadFile method which simply calls the update method and before returning the json file required. The next 2 methods are update and downloadFile which I think are my 2 issues, they are as follows

async update() {    
    let body = await this.downloadFile();
    const parsedJSON = JSON.parse(body);

    parsedJSON.updated_date = new Date();
    const json = JSON.stringify(parsedJSON);
    fs.writeFile('vatsimData.json', json, function(err, result) {
        if(err) console.log(err);
    });
}

downloadFile() {
    return new Promise((resolve, reject) => {
        const urlList = [
            'http://us.data.vatsim.net/vatsim-data.json',
            'http://eu.data.vatsim.net/vatsim-data.json',
            'http://apac.data.vatsim.net/vatsim-data.json'
        ];
        const url = urlList[Math.floor(Math.random()*urlList.length)];
        request(url, (error, response, body) => {
            if (error) reject(error);

            if (response.statusCode !== 200) {
                reject('Invalid status code <' + response.statusCode + '>');
            }

            resolve(body);
        });
    });
}

The output of the getSupervisors method should be an array of all the 'supervisors' within the json file, instead it returns Promise { <pending> } and this error

(node:3160) UnhandledPromiseRejectionWarning: SyntaxError: Unexpected end of JSON input
    at JSON.parse (<anonymous>)
    at DataHandler.loadFile (D:\Projects\VATSIM-Data-Handler\handler.js:57:15)
    at process._tickCallback (internal/process/next_tick.js:68:7)
(node:3160) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:3160) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

I have tried putting the whole of the update method within a .then callback after calling downloadFile but it did not work

My loadFile method is as follows

async loadFile(){
    await this.update();
    return(JSON.parse(fs.readFileSync('vatsimData.json', {encoding:'utf-8'})));
}

Upvotes: 0

Views: 3585

Answers (1)

Dhananjai Pai
Dhananjai Pai

Reputation: 6015

The reason you are getting a promise is because, you are not awaiting the async function when you console.log(handler.getSupervisors());

you should do

handler.getSupervisors.then(val => console.log(val));

The error may be because the body response from the server may be malformed. try console.log body before calling JSON.parse() and use try catch to wrap and prevent unhandled errors

Update From comments, you are trying to parse a file read with incorrect encoding

console.log(JSON.parse(fs.readFileSync('vatsimData.json',{encoding:'utf-8'})));

Add the encoding value in options.

Update

async update() {    
    let body = await this.downloadFile();
    const parsedJSON = JSON.parse(body);

    parsedJSON.updated_date = new Date();
    const json = JSON.stringify(parsedJSON);
    fs.writeFileSync('vatsimData.json', json, function(err, result) {
        if(err) console.log(err);
    }); // convert it to sync or resolve with a new promise when you complete the write to wait for the loadFile to have the file ready
}

Upvotes: 1

Related Questions