反应-Axios承诺未决值未定义

时间:2018-10-02 14:34:13

标签: javascript reactjs webpack axios autosuggest

我正在尝试使用React构建一个天气应用程序,react-autosuggest用于下拉列表列出可用的城市以及api获取Axios。

App.jsx

import React, { Component } from "react";
import CityWeather from './components/CityWeather';
import SearchWeather from './components/SearchWeather';




class App extends Component {

    constructor(props){
        super(props);
        this.state = {
            value: '',
            suggestedCities: [],
            cityWeatherData: [],
            currentWeather: [],
        }
    };

    handleCityWeatherData = (city) => {
        this.setState({
            cityWeatherData: city
        });
    };

    handleOnChange = (newValue) => {
        this.setState({
            value: newValue
        });
    }

    render() {

        // Finally, render it!
        return (
            <div>
                <SearchWeather suggestData={{value: this.state.value, suggestedCities: this.state.suggestedCities}} onSelectCity={this.handleCityWeatherData} onChange={this.handleOnChange}/>
                <CityWeather weatherData={this.state.cityWeatherData}/>
            </div>
        );
    }
}

export default App;

Apis.jsx

import Axios from "axios";

//local file
let cities = "./public/cities.json";


export default {
    getCities: function(){
        return  Axios.get(cities).then((res) => {
            console.log("from apis", res.data.cities);
            resolve(res.data.cities);
        }).catch((error) => {
            console.log("from apis.jsx", error);
            []
        });
    },
    getTest: function(){
        return 'hello';
    }
    //add api for weather
};

我在获取数据时遇到了麻烦,因此在SearchWeather.jsx中,我想使用函数const cities = apis.getCities()来获取城市列表,该函数从另一个文件{{ 1}},其中Apis.jsx方法使用Axios。错误发生在getCities中,在控制台中显示为api.getCities,并且我对<promise> pending变量未定义。不确定如何执行此操作,我尝试在cities中的await之前添加getCities,但没有执行任何操作。我可以使用api.jsx代替fetch,但我想使用Axios并了解更多信息。我确定它必须在Axios中进行,但不确定如何进行,我想我需要使用resolve而不知道如何做。新来的反应,所以我确定我错过了一些东西。您的帮助将不胜感激!

SearchWeather.jsx

const cities = apis.getCities()

注意:我将api调用放在另一个文件中只是为了组织的目的,并且希望保持这种方式,除非这不是正确的方式。

其他信息:

我将import React, { Component } from "react"; import Axios from "axios"; import Autosuggest from 'react-autosuggest'; import apis from '../utils/apis'; const getSuggestions = (value) => { const inputValue = value.trim().toLowerCase(); const inputLength = inputValue.length; const cities = apis.getCities().then((data) => { console.log(data); data; }); console.log('calling from getSuggestions'); console.log(cities); //this is undefined from const cities return inputLength === 0 ? [] : cities.filter(city => city.name.toLowerCase().slice(0, inputLength) === inputValue ); }; // When suggestion is clicked, Autosuggest needs to populate the input // based on the clicked suggestion. Teach Autosuggest how to calculate the // input value for every given suggestion. const getSuggestionValue = suggestion => suggestion.name; // Use your imagination to render suggestions. const renderSuggestion = suggestion => ( <span>{suggestion.name}</span> ); class SearchWeather extends Component { onChange = (event, { newValue }) => { this.props.onChange(newValue); }; // Autosuggest will call this function every time you need to update suggestions. // You already implemented this logic above, so just use it. onSuggestionsFetchRequested = ({ value }) => { this.setState({ suggestedCities: getSuggestions(value) }); }; // Autosuggest will call this function every time you need to clear suggestions. onSuggestionsClearRequested = () => { this.setState({ suggestedCities: [] }); }; renderSuggestionsContainer = ({ containerProps, children, query }) => { return ( <div {...containerProps}> {children} <h5>I like showing up.</h5> </div> ); }; fetchCityWeather = (cityId) => { //fetching sample request Axios.get("/public/sampleWeather.json").then((response) => { if(response.status === 200){ return response.data } else{ console.log('fetchCityWeather - something went wrong'); } }) .catch((error) => { console.log(error); }); }; onSuggestionSelected = (event, { suggestion, suggestionValue, suggestionIndex, sectionIndex, method }) => { console.log(suggestion); console.log(method); if(method == 'click'){ let cityId = suggestion.id; let data = this.fetchCityWeather(cityId); this.props.onSelectCity(data); //pass data to parent } }; componentDidMount = () => { console.log('componentDidMount'); } render(){ const value = this.props.suggestData.value; const suggestedCities = this.props.suggestData.suggestedCities; // Autosuggest InputProps const inputProps = { placeholder: 'Type your city', value, onChange: this.onChange }; return( <Autosuggest suggestions={suggestedCities} onSuggestionsFetchRequested={this.onSuggestionsFetchRequested} onSuggestionsClearRequested={this.onSuggestionsClearRequested} getSuggestionValue={getSuggestionValue} renderSuggestion={renderSuggestion} inputProps={inputProps} shouldRenderSuggestions = {(v) => v.trim().length > 0} renderSuggestionsContainer={this.renderSuggestionsContainer} onSuggestionSelected={this.onSuggestionSelected} /> ); } } export default SearchWeather; 更改为此:

const cities

我在控制台中注意到以下顺序:

来自const cities = apis.getCities().then((data) => { console.log("from getCities", data); return data; }); 中的console.log(cities)

SearchWeather

来自Promise {<pending>} Apis.jsx的数据

console.log("from apis", res.data.cities);

来自from apis (4) [{..},{..}]SearchWeather

console.log("from getCities", data);

不知道这是否有帮助,但是from getCities (4) [{..},{..}]被跳过然后返回并打印实际数据

2 个答案:

答案 0 :(得分:1)

Axios无法请求类似let cities = "./public/cities.json";的URL

如果将此json文件放在公用文件夹上,则可以设置类似的URL

http://localhost:3001/public/cities.json

不要忘记端口。这是对主机的HTTP请求,而不仅仅是读取本地文件。

答案 1 :(得分:0)

我注意到的第一件事是:

let cities = "./public/cities.json";

为了将文件读入代码,您必须使用require,如下所示:

let cities = require('./public/cities.json');

或如ES6

import cities from './public/cities.json'

任何能让您安心的东西。

我注意到的第二件事是,您在第一个承诺解决之后就返回了Axios(其中您根本不返回任何东西)。您可以这样:

getCities: function(){
   return  Axios.get(cities)
},

或者这个:

    getCities: function(){
        return  Axios.get(cities).then(res => res.data.cities).catch(...) // return cities
    },

这是为什么?

因为用.then函数将其包装后,您正在解决它,那么无论它在其中返回的内容如何,​​都将成为另一个保证,使您可以将其与另一个(或者在您的情况下)链接起来:

apis.getCities().then((data) => {
    const cities = data
});

如果使用我写的第一个,您将在此函数的data参数中返回响应。第二个将使您直接将城市变成数据。

编辑:

由于我误读了代码并且答案没有任何意义,所以我正在编辑答案:

为了获得异步诺言的响应,您必须向函数传递回调(或进行异步/等待),如下所示:

Apis.jsx

/**/
    getCities : cb => Axios.get(cities).then(res => cb(res.data.cities))
/**/

SearchWeather.jsx

const getSuggestions = (value, cb) => {
/**/
    apis.getCities().then(cities => {
       /* your logic to filter cities goes here */

       // return your filtered cities here 
       return cb(filteredCities)
    });
}

class SearchWeather extends Component{
/**/
    onSuggestionsFetchRequested = ({ value }) => {
        const cb = suggestedCities => this.setState({ suggestedCities })

        return getSuggestions(value, cb)
    };
/**/
}

cb(或回调)将在解决承诺后触发。