Javascript 重构react’;s componentDidMount()使用外部文件

Javascript 重构react’;s componentDidMount()使用外部文件,javascript,reactjs,asynchronous,callback,Javascript,Reactjs,Asynchronous,Callback,我使用的是react的组件didmount(),它包含大量代码并执行两次回调。最后,在最内部的回调(即第二个回调)中,我执行this.setState({}) 最小代码 class App extends React.Component { constructor(props) { super(props); this.state = { data: {} }; } requests() { fooCallback.request({ data: { que

我使用的是react的
组件didmount()
,它包含大量代码并执行两次回调。最后,在最内部的回调(即第二个回调)中,我执行
this.setState({})

最小代码

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { data: {} };
  }

  requests() {
    fooCallback.request({ data: { query: userQuery } }).subscribe(({ jsonResp1 }) => {

      // 100 lines of data processing with jsonResp1


      // second Callback
      barCallback.request({ data: { string: userString } }).subscribe(({ jsonResp2 }) => {

        // 200 lines of data processing with jsonResp2
        this.setState({ data: processedData })

      });
    });


    componentDidMount() {
      this.requests();
    }
  }

  render() {
    // ...
    return (
          // ...
        );
  }

}
由于
request()
方法非常庞大,它使我的主要容器组件应用程序膨胀。我已经尝试创建一个外部js文件(
默认导出函数…
),并将其导入到我的App.js中。然而,这是不可能的,可能是由于该方法的异步性质

是否有可能减少我的App.js

编辑

我在许多变体中尝试的是创建一个external.js文件:

external.js

。。。然后导入它

App.js


然而,没有成功。是创建类组件的唯一方法吗?

如果我正确理解您的问题,您希望将请求函数移动到一个单独的文件中,但在函数中使用“this.setState”,这超出了组件的范围

将此逻辑移出组件是正确的。有时使用回调会有点混乱,特别是当回调依赖于其他回调时,等等

如果回调是同步的,那不是很好吗?您可以通过将回调封装在承诺中并等待回调的结果进行解析来模拟这种情况。这样,您的程序将等待第一个回调完全执行并返回数据,然后再执行需要第一个回调输出的下一个回调(您要嵌套)

实用程序文件的外观如下所示:

function processRespOne(fooCallback, userQuery) {
  return new Promise((resolve, reject) => {
    fooCallback.request({ data: { query: userQuery } }).subscribe(({ jsonResp1 }) => {
      // ...process jsonResp1
      // by resolving this data, it acts like a standard function "return" if the invoking expression awaits it
      resolve(processedData);
    });
  });
}

function processRespTwo(respOneData, barCallback, userString) {
  return new Promise((resolve, reject) => {
    barCallback.request({ data: { string: userString } }).subscribe(({ jsonResp2 }) => {
      // process jsonResp2 with the output of respOneData
      resolve(processedData);
    });
  });
}


// here I define the function "async" so i can use the "await" syntax, so my asynchronous function acts synchronous 
// Async functions return promises. So caller's can await this function.
export async function requests(fooCallback, userQuery, barCallback, userString) {
  const respOneData = await processRespOne(fooCallback, userQuery);
  const results = await processRespTwo(respOneData, barCallback, userString)

  // anyone who is "await"ing this function will get back results
  return results;
}
在App.js中

import { requests } from './js/getData.js';
//...
   async componentDidMount() {
     const results = await requests(fooCallback, userQuery, barCallback, userString);
     this.setState({ results });
   }

这里有一个链接指向一个非常好的答案,讨论如何将回调转换为承诺,以实现更同步的执行。一定要看看公认答案中的“Nodeback”示例:

我真的不明白问题所在,加载数据时应用程序挂起了?@PrinceHernandez我不想减少容器组件中的行数。在我的渲染方法中,所有操作都由外部加载的组件完成,并在外部执行它们的操作。我希望request()方法具有相同的行为。正如我在回答中提到的,我认为您可能需要重新考虑如何处理回调和异步操作。尝试用承诺包装回调,这样您就可以通过解析回调中的结果来等待回调的结果谢谢@Julian。明天早上我就试试。但是,第二个回调的输入取决于第一个回调中的一些已处理数据。所以我不能把它们分开…哦,明白了,我稍后也会更新我的答案。这个故事的寓意是通过将回电包装在承诺中来承诺回电,这样你的结果就可以等待。谢谢你的帮助。我仍在努力解决异步问题。。。我很想测试您的代码…一开始它非常混乱,但一旦您理解了它,节点作为一个整体就变得更容易理解,因为语言中最不可预测的部分是异步代码的处理方式。我没有检查代码,所以如果代码不起作用,请告诉我,我可以做一支代码笔或其他什么对不起,花了这么长时间。你的方法非常适合我的案子!谢谢!
function processRespOne(fooCallback, userQuery) {
  return new Promise((resolve, reject) => {
    fooCallback.request({ data: { query: userQuery } }).subscribe(({ jsonResp1 }) => {
      // ...process jsonResp1
      // by resolving this data, it acts like a standard function "return" if the invoking expression awaits it
      resolve(processedData);
    });
  });
}

function processRespTwo(respOneData, barCallback, userString) {
  return new Promise((resolve, reject) => {
    barCallback.request({ data: { string: userString } }).subscribe(({ jsonResp2 }) => {
      // process jsonResp2 with the output of respOneData
      resolve(processedData);
    });
  });
}


// here I define the function "async" so i can use the "await" syntax, so my asynchronous function acts synchronous 
// Async functions return promises. So caller's can await this function.
export async function requests(fooCallback, userQuery, barCallback, userString) {
  const respOneData = await processRespOne(fooCallback, userQuery);
  const results = await processRespTwo(respOneData, barCallback, userString)

  // anyone who is "await"ing this function will get back results
  return results;
}
import { requests } from './js/getData.js';
//...
   async componentDidMount() {
     const results = await requests(fooCallback, userQuery, barCallback, userString);
     this.setState({ results });
   }