Home > OS >  Callback with recursive functions
Callback with recursive functions

Time:07-02

I am using the google translate api to translate data from a json file to french locale and then write it back to a file. I am using a recursive function to iterate over the json file since it is deeply nested. However the execution is not waiting till the translation is completed before it writes to the file. I have tried using callback and promise approaches but i couldn't get it right.

Just for it to work as I required an output as an emergency I have set a timout before the write method is called. It work but I would like to learn the appropriate/correct approach to implement this.

const fs = require('fs')
const {Translate} = require('@google-cloud/translate').v2
require('dotenv').config()
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0

const credentials = JSON.parse(process.env.credentials)

const translate = new Translate({
    credentials,
    projectId: credentials.project_id,
})

let data = {}

// writeJSONTofile should be executed only after readJSONFile execution is completed

//read file
const readJSONFile = () => {
    try {
        data = JSON.parse(fs.readFileSync('...\\locale\\en.json'))
        iterateAndTranslate(data)

        setTimeout(() => {
            writeJSONToFile() 
        }, 25000) 
    } catch (error) {
        console.log(error)
    }
}

// iterate, translate, reassign
const iterateAndTranslate = async (data) => {
    for(key in data) {
        if (typeof data[key] === 'object' && data[key] !== null) {
            iterateAndTranslate(data[key])
        } else{
            data[key] = await translateText(data[key], 'fr')
        }
    } 
}


//translate method
const translateText = async (text, targetLanguage) => {
    try {
        let [response] = await translate.translate(text, targetLanguage)
        return response
    } catch (error) {
        console.log(error)
        return 0
    }
}

const writeJSONToFile = async () => {
    var outputFileName = 'C:\\test\\test.json'
    await fs.writeFileSync(outputFileName, JSON.stringify(data,null,4), (err) => {
        if(err) {
            console.log(err)
        } else {
            console.log('Done!')
        }
    })
}

// start from here 
readJSONFile()

CodePudding user response:

You have a few issues with your code.

  • Your functions use a global variable and mutate it instead of getting input and returning output.
  • timeout will cause unexpected behavior in your case.
  • you are using var
  • you have redundant async-await on the writeJSONToFile function

See my view of point about the possible solution.

  const fs = require("fs");
  const { Translate } = require("@google-cloud/translate").v2;
  require("dotenv").config();
  process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;

  const credentials = JSON.parse(process.env.credentials);

  const translate = new Translate({
    credentials,
    projectId: credentials.project_id,
  });

  // writeJSONTofile should be executed only after readJSONFile execution is completed

  //read file
  const readJSONFile = async () => {
    try {
      const data = JSON.parse(fs.readFileSync("...\\locale\\en.json"));
      return iterateAndTranslate(data);
    } catch (error) {
      console.log(error);
    }
    return {};
  };

  // iterate, translate, reassign
  const iterateAndTranslate = async (data) => {
    for (let key in data) {
      if (typeof data[key] === "object" && data[key] !== null) {
        await iterateAndTranslate(data[key]);
      } else {
        data[key] = await translateText(data[key], "fr");
      }
    }
    return data;
  };

  //translate method
  const translateText = async (text, targetLanguage) => {
    try {
      let [response] = await translate.translate(text, targetLanguage);
      return response;
    } catch (error) {
      console.log(error);
    }
    return null;
  };

  const writeJSONToFile = (data) => {
    let outputFileName = "C:\\test\\test.json";
    fs.writeFileSync(outputFileName, JSON.stringify(data, null, 4), (err) => {
      if (err) {
        console.log(err);
      } else {
        console.log("Done!");
      }
    });
  };

  // start from here
  const run = async () => {
    const data = await readJSONFile();
    writeJSONToFile(data);
  };
  run();

See more:

  • Related