ReactJS -> сохранить переменную из обещания - PullRequest
0 голосов
/ 18 сентября 2018

Я пытаюсь выяснить, как сохранить этапы возврата обещания в переменные.В этом случае я использую карты Google и геокодер Google, чтобы преобразовать файл адресов JSON в массив объектов lat lng для создания маркеров, но мне все равно любопытно.Это было сделано с помощью одного обещания, но, поскольку я вынужден циклически проходить через данные и выполнять вызов, я не могу вызвать другую функцию и оставить обещание, поскольку в конечном итоге мне придется повторить обещание.Это означает, что мне нужно хранить объект в отдельной переменной.См. Разделы кода ниже.

address.json

{ 
  "address" : "Oosterpark 9",
  "city" : "Amsterdam",
  "name" : "Onze Lieve Vrouwe Gasthuis"
  "zipcode" : "1091 AC"
},
{
  "address" : "Jan Tooropstraat 164",
  "city" : "Amsterdam",
  "name" : "Sint Lucas Andreas Hospital"
  "zipcode" : "1061 AE"
}

Map.js

makeMarker(a){
    Geocode.setApiKey(this.apiKey);
    let arr = [];
    for(let i=0; i < a.length; i++){
        let address = b[i].address.replace(" ","+") + ',+'+b[i].zipcode.replace(" ","+")+',+'+b[i].city;

        arr[i] = Geocode.fromAddress(address).then(
            response => {
                const {lat, lng} = response.results[0].geometry.location;
                console.log(lat, lng);
                return {lat: lat, lng: lng};
            }
        );
    }
return arr;
}

В этом случае вышеупомянутая функция вызывается в конструкторе, гдепеременная ожидает определения в результате выполнения функции makeMarker.В этом случае он возвращает только [обещание, обещание], когда он должен вернуть [{lat: __, lng: __,}, {lat: __, lng: __,}].

Я надеюсь услышать некоторые ваши идеи о том, как решить этот вариант использования!

Ответы [ 2 ]

0 голосов
/ 18 сентября 2018

@ Sagiv b.g ответ об использовании Promise.all - лучший способ. Вот другой подход.

var arr = [];
makeMarker(a){
    Geocode.setApiKey(this.apiKey);
   
    for(let i=0; i < a.length; i++){
        let address = b[i].address.replace(" ","+") + ',+'+b[i].zipcode.replace(" ","+")+',+'+b[i].city;

        Geocode.fromAddress(address).then(
            response => {
                const {lat, lng} = response.results[0].geometry.location;
                console.log(lat, lng);
                 addToArr({lat: lat, lng: lng},b);
            }
        );
    }

}

addToArr(latLongObj,b){
  arr.push(latLongObj);
  if(arr.length >= b.length){
    //callYourfunction and do the logic
  }
}
0 голосов
/ 18 сентября 2018

Вы можете использовать Promise.all , создать массив обещаний на экземпляре class, затем на componentDidMount (или другом полезном хуке жизненного цикла):

Promise.all(promies).then(...)

Так что-то вроде этого:

makeMarker(a){
    Geocode.setApiKey(this.apiKey);
    let arr = [];
    for(let i=0; i < a.length; i++){
        let address = b[i].address.replace(" ","+") + ',+'+b[i].zipcode.replace(" ","+")+',+'+b[i].city;

        arr[i] = Geocode.fromAddress(address)
    }
    this.promises = arr;
}

Тогда в другом месте вашего кода:

Promise.all(this.promises).then(
  listOfResponses => {
     // rest of your code
  }
)

Вот небольшой пример такого использования с Promise.all

const data = [1, 2, 3, 4, 5, 6];

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      fetchedData: []
    }
    this.promises = data.map(d => {
      return new Promise((resolve) => {
        setTimeout(() => resolve(d),1500);
      })
    });
  }

  componentDidMount() {
    Promise.all(this.promises).then(fetchedData => this.setState({ fetchedData }));
  }
  
  render() {
    const { fetchedData } = this.state;
    return (
      <div>
        {fetchedData.length ? fetchedData.map(d => <div>{d}</div>) : "Loading..."}
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
...