需要通过代码的执行才能在Javascript中得到输出

Need to pass the execution of code to get output in Javascript

我在 React 应用程序中为 translation 使用以下代码。它的遗留应用程序。所以它们都是 class 组件和旧库。

import i18next from 'i18next';
import React from 'react';
import TransFile from './TransFile.js';

const LanguageDetector = require('i18next-browser-languagedetector');
const initReactI18next = require('react-i18next');
var output;
//API call
apiDelegate.getTranslations().then((result) => {
  output = JSON.stringify(result);
  alert("output1 =>"+result);

});

alert("output2 is:"+output);

  i18next
    .use(LanguageDetector)
    .use(initReactI18next)
    .init({
      resources: {
        en: output, //Here I need to assign output
      },
      fallbackLng: 'fr',
});
i18next.changeLanguage(navigator.language);
alert("Output3 is:"+output);
export default i18next;

它正在打印 output2 的警报,然后是 output3,然后是 output1output2output1undefined。我需要按顺序打印它们,因为我需要在我的应用程序中使用 API 数据。它没有分配给实际变量 基本上我需要将 output 分配给我的 en 变量。代码行下方

 en: output,

我不能使用 async await 因为 babel 不是 supporting 并且它是相当旧的应用程序所以当我更新 webpack 时失败。 apiDelegate代码。

getTranslations() {
    var token = sessionStorage.getItem('jwt');
    if (token == null) {
      token = '';
    }
    return new Promise((resolve) => {
      request
        .get(baseUrl.api + '/file_download/en')  //API call
        .set({
          'Content-Type': 'application/json',
          Authorization: 'Bearer ' + token,
        })
        .then((value) => {
          var result;
          if (value.status === 200) {
            result = value.body;
            // alert(JSON.stringify(result));
          }
          resolve(result);
          return result;
        })
        .catch((error) => {
          var result;
          if (error.status === 401 || error.status === 403) {
            result = { status: -2, message: error, data: [] };
          }
          resolve(result);
        });
    });
  }

可以使用 callbacksetTimeOut 来完成吗?我知道它的基本知识,但我是初学者。无法解决同样的问题。请帮忙

编辑1:- 数据将存储在文件中,否则 API 输出将如下所示。

translation: {
        app_header:"My contact",
        app_address:"my address",
        app_phone:"+1 93244 3223",
        app_email:"abc@abc.com"
  }

我在我的文件中使用 i18,如下所示。

import i18n from '../../../i18'

在组件中它将像下面这样使用

i18n.t("app_header")

因此 app_header 的值将在应用程序中被替换。

因为你有apiDelegate fn的依赖,你需要在调用API之后初始化i18next。然后只有你可以访问输出变量结果。

import i18next from 'i18next';
import React from 'react';
import TransFile from './TransFile.js';

const LanguageDetector = require('i18next-browser-languagedetector');
const initReactI18next = require('react-i18next');

//API call
apiDelegate.getTranslations().then((result) => {
  var output;
  output = JSON.stringify(result);
  alert("output1 =>"+result);

  //Moved the assigning logic here
  i18next
  .use(LanguageDetector)
  .use(initReactI18next)
  .init({
    resources: {
      en: output, //Here I need to assign output
    },
    fallbackLng: 'fr',
  });
   console.log('Output set to en', output)
  i18next.changeLanguage(navigator.language);
});

export default i18next;

如需详细解答,请在此处附上示例反应代码,

  1. 我收到来自 API/FN 的翻译回复,将在 5 秒后 return
  2. 获得响应后,使用 API 结果
  3. 初始化 i18next

无需导出 i18next ,获取结果后在您的主应用程序中调用它即可。

import React, { useState } from "react";
import i18next from 'i18next';

function App(){
  const [result,setResult] = useState('')

  getTranslationFromAPi().then( response => {
    i18next
    .init({
      resources: {
        en: response, //Here I need to assign output
      },
      fallbackLng: 'fr',
    });
    i18next.changeLanguage(navigator.language);
  })
  
  //Mock funtion gives response after 5sec
  function getTranslationFromAPi(){
    return new Promise((resolve, rej)=>{
      setTimeout(() => {
        resolve({translation:{ln:'sample lang'}});
      }, 5000);
    })
  }

  setTimeout(() => {
    setResult(i18next.t('ln'))
  }, 10000);

  return(
    <div>
      {/* Result will come after 10 sec */}
      {result}  
    </div>
  )
}

export default App;

我发现您的代码有几个问题。最重要的是,正如评论中提到的,您始终必须确保保持承诺链的运行。在 apiDelegate 中,您不必 return 一个新的承诺,只需 return 现有的请求。无论如何,请求已被弃用。此外,您所有的进口商品都有些混乱。在您的组件中,您必须确保只调用 i18 的 init 一次。我使用 useEffect 来实现它。 我试图用一个假的 api 为您制作一个 sample application 用于演示目的,以便您调试代码。您可以简单地注释掉 apiDelegate 中的行以使用 fetch 方法调用您真正的 api.

App.js

import i18n, { t } from "i18next";
import React, { useEffect, useState } from "react";
import { getTranslations } from "./apiDelegate";
import { initReactI18next } from "react-i18next";
import LanguageDetector from "i18next-browser-languagedetector";

export default function App() {
  const [init, setInit] = useState(false);

  //API call
  useEffect(() => {
    (function () {
      getTranslations().then((result) => {
        alert("output1 =>" + result);

        i18n
          .use(initReactI18next)
          .use(LanguageDetector)
          .init({
            resources: {
              en: (alert("output2 =>" + JSON.stringify(result)), result) //Here I need to assign output
            },
            fallbackLng: "fr"
          })
          .then(() => {
            //i18n.changeLanguage(navigator.language);
            i18n.changeLanguage("en");
            setInit(true);
          });
      });
    })();
  }, []);

  return (
    <div i18nready={init.toString()} className="App">
      <div>{t("app_header")}</div>
    </div>
  );
}

apiDelegate.js

//import request from "request"; deprecated

export const getTranslations = () => {
  var token = sessionStorage.getItem("jwt");
  if (token == null) {
    token = "";
  }

  // return fetch(baseUrl.api + '/file_download/en', {  //when using api
  return fetch(
    //remove line when using api
    "./translation.json" //remove line when using api
    /*     , {   //when using api
    method: 'post',
    headers: new Headers({
      'Authorization': "Bearer " + token,
      "Content-Type": "application/json",
      Accept: "application/json"
    }),
    body: 'A=1&B=2'
  } */
  )
    .then((res) => res.json())
    .then((result) => {
      /*       if (result.status === 200) {  //when using api
        return result.body;
      } */
      if (Object.entries(result).length) return result; //remove line when using api

      return { status: -2, message: result.status, data: [] };
    })
    .catch((error) => {
      return { status: -2, message: error.message, data: [] };
    });
};
import i18n from "i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import backend from 'i18next-http-backend';
import api from "../api";

 var lang=navigator.language;

let loadResources= apiDelegate.getTranslations(lang);
const backendOptions = {
  loadPath: 'http://localhost:8080/code/'+lang, 
  request: (options, url, payload, callback) => {
    try {
      loadResources.then((result) => {
        callback(null, {
          data: result,
          status: 200, 
        });
      });
    } catch (e) {
      console.error(e);
      callback(null, {
        status: 500,
      });
    }
  },
};

i18n
  .use(LanguageDetector)
  .use(backend)
  .init({
    backend: backendOptions,
    fallbackLng: "fr",
    debug: false,
    load:"languageOnly",
    ns: ["translations"],
    defaultNS: "translations",
    keySeparator: false, 
    interpolation: {
      escapeValue: false, 
      formatSeparator: ","
    },
    react: {
      wait: true
    }
});
i18n.changeLanguage(navigator.language);
export default i18n;