首页 文章

无法使用React中追踪的Promises返回的数据进行setst

提问于
浏览
0

我使用React和promises,我有2个函数 . 第一个返回数据 . 我调用第二个函数时使用的数据 - 我在其中发出get请求(调用我正在进行实际get请求的函数) . 我尝试存储来自第二个函数调用集状态的响应,但是,它总是未定义或我收到错误:

无法设置未定义的状态 .

在我的代码中 - 当我记录'test'时,它也是未定义的,所以某种程度上这个值没有存储/或者可能没有返回任何地方,但我不知道该怎么做 .

class App extends React.Component {
  handleInput() {
    multipleAirports(this.state.input.origin.value).then(response => {
        var result = [];
        var test = [];
        var input = this.state.input;
        for (var i = 0; i < response.Airports.length; i++) {
            result.push(anyDestinationData(response.Airports[i].code, input.departuredate, input.returndate, input.maxfare))

           return Promise.all(result).then(function (results) {
                var data = [];
                results.forEach(function (item) {
                    data.push({
                        [item.data.OriginLocation]: item.data.FareInfo
                    })

                });
                test = data;
            })
        }
        this.setState({
            flightData: test
        })
    })
        .then(response => {
            console.log("resreeeee", response)

        })
  }
}

4 回答

  • 0

    为什么你在for循环中返回了Promise.all?用你需要的东西填充 result 然后将它用于Promise.all() . 当这些承诺中的每一个都得到解决时,您将在then()中收到输出 . 我假设 anyDestinationData 在这里是一个承诺 . 还可以在任何地方添加控制台,以便在它成为 undefined 时进行检查 .

  • 1

    这两部分是有问题的:

    • 在循环内调用并返回 Promise.all
    for (var i = 0; i < response.Airports.length; i++) {
       result.push(anyDestinationData(response.Airports[i].code, input.departuredate, input.returndate, input.maxfare))
    
       return Promise.all(result).then(function (results) {
    

    一旦遇到 return 语句,该函数的执行将不会继续 . 将它置于没有条件的循环中将始终导致函数在第一次迭代中停止执行(假设满足循环条件) .

    在您的情况下, result 数组在传递给 Promise.all 之前将始终包含一个元素,并返回结果承诺 .

    • 引用错误的 this 内部函数 - 其值在函数调用时确定,而不是函数定义(不是箭头函数的情况) .
    return Promise.all(result).then(function(results) {
       //...
       this.setState({
    

    这应该工作:

    class App extends React.Component {
      handleInput() {
        multipleAirports(this.state.input.origin.value).then( response => {
          // Populate the array.
          const result = response.Airports.map(airport => anyDestinationData(airport.code, input.departuredate, input.returndate, input.maxfare));
    
          // Pass it to `Promise.all` and return it.
          return Promise.all(result).then( results => {
            const data = results.map(item => ({ [item.data.OriginLocation]: item.data.FareInfo }))
            this.setState({
              flightData: data
            })
          })   
        })
        .then(response => {
          console.log("resreeeee", response)
        })
      }
    }
    

    注意我用 .map 调用替换 for 循环,用 const / let 替换 var ,因为您已经在使用ES7功能 .

  • 1

    由于以下原因, this.setState() 没有按照你的意愿行事:

    for 循环内部返回的

    • 不仅终止循环,还终止整个 .then() 回调 .

    • Promise.all(result).then(...) 需要在循环之外 .

    • this.setState 需要在 Promise.all(result).then(...) 回调中 .

    这里的目标比最初出现的目标要简单得多 .

    您寻求的基本模式是:

    myFn() {
        // return a Promise to myFn's caller - shouldn't hurt even if not necessary
        return doSomethingAsync()
        .then(response => {
            // map `responses` to an array of promises
            var promises = response.map(item => doSomethingElseAsync(item));
            // aggregate `promises` and return a promise that delivers an array of results from doSomethingElseAsync().
            return Promise.all(promises);
        })
        .then(data => {
            // do something with <Array> `data`
            this.setState({
                flightData: data.map(/* some transform of `data` */)
            });
            return data; // optional - deliver `data` (via the returned Promise) to myFn's caller.
        });
    }
    

    在全 :

    class App extends React.Component {
        handleInput() {
            var input = this.state.input;
            return multipleAirports(input.origin.value)
            .then(response => {
                // map `response.Airports` to an array of promises (originally named `result`)
                var promises = response.Airports.map(airport => anyDestinationData(
                    airport.code,
                    input.departuredate,
                    input.returndate,
                    input.maxfare
                ));
                // aggregate `promises` and return a Promise that delivers an array of flights (presumably).
                return Promise.all(promises);
            })
            .then(flights => {
                // map `flights` to array of specialised objects
                var data = flights.map(item => {
                    return { [item.data.OriginLocation]: item.data.FareInfo };
                });
                this.setState({
                    flightData: data
                });
                return data; // optional - make `data` (or `flights`?) available to handleInput's caller.
            });
        }
    }
    

    备注:

    • 承诺提供数据虽然有时很方便,但很少需要通过外部成员来提供数据 . 问题的 var test 是不必要的 .

    • Array.prototype.map()使代码非常简洁(两次) .

  • 0
    class App extends React.Component {
        handleInput = () => {
            const {
              input,
              input: { origin: {
                value
              }}
            } = this.state;
    
            multipleAirports(value)
              .then((response) => {
                  const results = response.Airports.map(airport => anyDestinationData(airport.code, input.departuredate, input.returndate, input.maxfare));
    
                  return Promise.all(results)
                    .then((result) => {
                      results.map((item) => {
                        const data = result.map(item => ({
                          [item.data.OriginLocation]: item.data.FareInfo
                        }))
                        this.setState({
                          flightData: data
                        })
                      })
                    })
                    .then(response => {
                      console.log("resreeeee", response)
                    })
                }
              }
    

    我稍微修改了你的代码,请看看是否有效 . 我把 Promise.all 从循环中取出然后 setState 在诺言中 .

相关问题