-1

I have a async function translateText() which return some response, I am trying to put that response in a different file where the function will call, but it is not working at all. giving error.

TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. 
Received an instance of Promise
  • I have a array ImagesNames which contains file name.

  • detecText() is coverting txt from Images and pass response in translateText()

  • After this I am trying to use the response of detecText() in TranslateText() and response of translate text I am trying to save in .txt file where filename will be ImagesNames array or detecTxt parameter

  • Now I am passing this array filename in writeFileSync where text is coming from translateText() function

translateText function

    const target = "en";
    
    const translateText = async function translateText(text) {
      let [translations] = await translate.translate(text, target);
      translations = Array.isArray(translations) ? translations : [translations];
    
      translations.forEach((translation, i) => { 
        return translation;
      });
    }; 

Using function to write response in .txt

   ImagesNames.forEach((element) => {
    detecText(element)
    .then((result) => {
    texts = result;
    let imagesdir = element.replace("public/", "");
    finaltextsave = imagesdir.replace(".jpg", ".txt");
     fs.writeFileSync(finaltextsave, translateText(result));

   })
   .catch((err) => console.log(err + element));

    });

How Can I save this response of translateText() and parameter of detecText() as a file name for every loop running or every parameter.

Updated as suggested by below answers -

still getting error but a bit different.

TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. 

Received an instance of array.

 ImagesNames.forEach((element) => {
 detecText(element)
 .then(async (result) => { 
  texts = result;
  let imagesdir = element.replace('public/', '');
  finaltextsave = imagesdir.replace('.jpg', '.txt');
  fs.writeFileSync(finaltextsave, await translateText(result)); 
})
.catch((err) => console.log(err + element));

});

kate moss
  • 416
  • 1
  • 5
  • 18

2 Answers2

1

To resolve the issue of cannot write undefined to file as Buffer or String instance was extepected we have to take a look at the translateText function. We can remove the .forEach as it does not do anything use because the return statement is related to the callback of .forEach and not translateText. Leaving us with the snippet below. Now translateText returns a Promise of an array.

const translateText = async function translateText(text) {
  let [translations] = await translate.translate(text, target);
  translations = Array.isArray(translations) ? translations : [translations];

  return translations;
};

Every async function automatically returns a Promise. Therefore the return values of translateText is a Promise. fs.writeFileSync on the other hand can only work with strings or buffers. To resolve the issue you are facing the callback of your .then call on detecText also has to be asynchronous so you can await translateText. Now that translateText returns Promise<Array> we store the array in a seperate variable and use a looping mechanism of our choice to iterate over all translations in translations. In that loop we then write each translation to it's own file using it's position in the array as unique value for the file names.

ImagesNames.forEach((element) => {
  detecText(element)
    .then(async (result) => {
      //  ^^^^^ add async here to create async context
      texts = result;
      let imagesdir = element.replace('public/', '');
      finaltextsave = imagesdir.replace('.jpg', '.txt');
      let translations = await translateText(result);
      //                 ^^^^^ add await here to wait for the translations
      translations.forEach((translation, index) => {
        let [path, extension] = finaltextsave.split('.');
        fs.writeFileSync([path, `_${index}`, '.txt'].join(''), translation);
      });
    })
    .catch((err) => console.log(err + element));
});
Palladium02
  • 1,134
  • 1
  • 4
  • 13
  • got error `TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received undefinedpublic/8773-20220804-1-Cover Page_5.jpg` here I am removing `public/` and `replacing .jpg` with .txt from element to save as file name – kate moss Aug 26 '22 at 12:02
  • @katemoss Is that error from the same location in your code? – Palladium02 Aug 26 '22 at 12:19
  • this error coming from `.catch((err) => console.log(err + element));` as err is undefined and file name is `public/8773-20220804-1-Cover Page_5.jpg` – kate moss Aug 26 '22 at 12:28
  • 1
    Know I see your are passing undefined as data to `writeFileSync` as `translateText` does not return anything and therefore the value of the Promise will be `undefined`. – Palladium02 Aug 26 '22 at 12:34
  • as you can see I am removing `public/` and replacing `.jpg` with .txt to save with this file name in `fs.writeFileSync` – kate moss Aug 26 '22 at 12:34
  • 1
    @katemoss Yes but you are trying to write `undefined` to a file because `translateText` does not return anything. – Palladium02 Aug 26 '22 at 12:36
  • but it cannot be possible as I have 3 elements in an array which is passing in `detecText` as element then passing the same element in `translatText()` – kate moss Aug 26 '22 at 12:40
  • 2
    @katemoss You are missing the return statement in `translateText`. – Palladium02 Aug 26 '22 at 12:44
  • Oh! but you can see above in `translateText()` **function** I already use return statement – kate moss Aug 26 '22 at 12:55
  • @katemoss Sorry for the delay there also has to be one outside of the `forEach` in order for the function to return something. – Palladium02 Aug 26 '22 at 18:10
  • I have updated outside foreach loop, could you please update your answer with this return ? – kate moss Aug 27 '22 at 17:05
  • @Palladium02 how can we save this .txt in a folder or another direcotry ? – Utsav Upadhyay Sep 04 '22 at 07:22
0

You could try this:

ImagesNames.forEach(async (element) => {
    try {
      let text = await detecText(element);
      let translatedText = await translateText(text);
      let imagesdir = element.replace("public/", "");
      finaltextsave = imagesdir.replace(".jpg", ".txt");
      fs.writeFileSync(finaltextsave, translatedTexts);
    } catch (err) {
      console.log(err + element)
    }
  }
);
Ernest Wambua
  • 153
  • 1
  • 6
  • got error `TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received undefinedpublic/8773-20220804-1-Cover Page_5.jpg` here I am removing `public/` and `replacing .jpg` with .txt from element to save as file name – kate moss Aug 26 '22 at 11:59