-1

Considering a simple function that should load a .json file dynamically and conditionally, then return a specific key from this file as below:

export const translate = async (key: string, from: string) =>
  await import(`../locales/www/${from}.json`)
    .then((translations) => {
      const translation = translations.default[key];
      console.log(translation);      // console.log() works
      // Promise.resolve(translation);
      return translation;            // returns a promise object not the value
    })
    .catch((err) => console.log(err));



// In another file
translate(a, b) 

I can't understand why it doesn't return a value (wanted behaviour) but a Promise.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
charnould
  • 2,480
  • 3
  • 19
  • 23
  • Because it's an async function. They _always_ return promises. – jonrsharpe May 23 '23 at 08:06
  • 1
    Does this answer your question? [How to return values from async functions using async-await from function?](https://stackoverflow.com/questions/49938266/how-to-return-values-from-async-functions-using-async-await-from-function) – jonrsharpe May 23 '23 at 08:09

2 Answers2

1
  • Async functions always returns Promise, to extract its value you have to call with await ( await translate(a, b)).
  • JSON import using import is a very new feature and not available in older versions of node.
  • Never call Promises with await or .then simultaneously
import fs from 'fs/promises'
import path from 'path'

const __dirname = path.dirname(new URL(import.meta.url).pathname)

export const translate = async (key: string, from: string) => {
  try {
    const translationsFile = await fs.readFile(path.join( __dirname, `../locales/www/${from}.json`))
    const translations =  JSON.parse(translationsFile)
    return translations[key] 
  } catch (error) {
    console.error(error)
    return 
  }
}


// another file
// const value = await translate(<key>, <from>)

bogdanoff
  • 1,705
  • 1
  • 10
  • 20
0

Some notices:

  1. avoid using .then() whenever possible. this will make your life easier
  2. seems your json file isn't json but js. because if you import json in node your way it will throw ERR_IMPORT_ASSERTION_TYPE_MISSING. You should assert or read the json file manually and resolve relative paths yourself using import.meta.url.
  3. you shouldn't use await for return values because it blocks execution of the caller. the caller should decide itself what to do with the returned promise, wait or continue.
  4. move your catch to the caller, it knows better what to do with the error. otherwise you just usually rethrow it.
  5. since you're using an async function you should use await when using it.

So on my node 18 this works fine:

export const translate = async (key, from) => {
    const { default: translations } = await import(`../locales/www/${from}.json`, { assert: { type: 'json' } });
    return translations[key];
}

usage:

await translate(key, from);
Alexander Nenashev
  • 8,775
  • 2
  • 6
  • 17