usar una termine que promesas programacion funcion esperar entre ejemplo ejecucion diferencia cuando controlar callbacks await async asincronia asincrona javascript reactjs state

javascript - promesas - React.js, ¿espera que setState termine antes de activar una función?



programacion asincrona javascript (3)

Aquí está mi situación:

  • en this.handleFormSubmit () Estoy ejecutando this.setState ()
  • dentro de this.handleFormSubmit (), estoy llamando this.findRoutes (); - que depende de la finalización exitosa de this.setState ()
  • this.setState (); no se completa antes de this.findRoutes se llama ...
  • ¿Cómo espero a que this.setState () dentro de this.handleFormSubmit () termine antes de llamar this.findRoutes ()?

Una solución deficiente:

  • poniendo this.findRoutes () en componentDidUpdate ()
  • esto no es aceptable porque habrá más cambios de estado no relacionados con la función findRoutes (). No quiero activar la función findRoutes () cuando se actualiza el estado no relacionado.

Consulte el fragmento de código a continuación:

handleFormSubmit: function(input){ // Form Input this.setState({ originId: input.originId, destinationId: input.destinationId, radius: input.radius, search: input.search }) this.findRoutes(); }, handleMapRender: function(map){ // Intialized Google Map directionsDisplay = new google.maps.DirectionsRenderer(); directionsService = new google.maps.DirectionsService(); this.setState({map: map}); placesService = new google.maps.places.PlacesService(map); directionsDisplay.setMap(map); }, findRoutes: function(){ var me = this; if (!this.state.originId || !this.state.destinationId) { alert("findRoutes!"); return; } var p1 = new Promise(function(resolve, reject) { directionsService.route({ origin: {''placeId'': me.state.originId}, destination: {''placeId'': me.state.destinationId}, travelMode: me.state.travelMode }, function(response, status){ if (status === google.maps.DirectionsStatus.OK) { // me.response = response; directionsDisplay.setDirections(response); resolve(response); } else { window.alert(''Directions config failed due to '' + status); } }); }); return p1 }, render: function() { return ( <div className="MapControl"> <h1>Search</h1> <MapForm onFormSubmit={this.handleFormSubmit} map={this.state.map}/> <GMap setMapState={this.handleMapRender} originId= {this.state.originId} destinationId= {this.state.destinationId} radius= {this.state.radius} search= {this.state.search}/> </div> ); } });


Según los documentos de setState() el nuevo estado podría no reflejarse en la función de devolución de llamada findRoutes() . Aquí está el extracto de React docs :

setState () no muta inmediatamente this.state pero crea una transición de estado pendiente. Acceder a this.state después de llamar a este método puede devolver el valor existente.

No hay garantía de operación síncrona de llamadas a setState y las llamadas pueden ser agrupadas para obtener ganancias de rendimiento.

Entonces, esto es lo que les propongo que hagan. Debe pasar la input nuevos estados en la función de devolución de llamada findRoutes() .

handleFormSubmit: function(input){ // Form Input this.setState({ originId: input.originId, destinationId: input.destinationId, radius: input.radius, search: input.search }); this.findRoutes(input); // Pass the input here }

La función findRoutes() debe definirse así:

findRoutes: function(me = this.state) { // This will accept the input if passed otherwise use this.state if (!me.originId || !me.destinationId) { alert("findRoutes!"); return; } var p1 = new Promise(function(resolve, reject) { directionsService.route({ origin: {''placeId'': me.originId}, destination: {''placeId'': me.destinationId}, travelMode: me.travelMode }, function(response, status){ if (status === google.maps.DirectionsStatus.OK) { // me.response = response; directionsDisplay.setDirections(response); resolve(response); } else { window.alert(''Directions config failed due to '' + status); } }); }); return p1 }


setState() tiene un parámetro de devolución de llamada opcional que puede usar para esto. Solo necesita cambiar su código ligeramente, para esto:

// Form Input this.setState( { originId: input.originId, destinationId: input.destinationId, radius: input.radius, search: input.search }, this.findRoutes // here is where you put the callback );

Observe que la llamada a findRoutes ahora está dentro de la llamada setState() , como el segundo parámetro.
Sin () porque está pasando la función.


this.setState( { originId: input.originId, destinationId: input.destinationId, radius: input.radius, search: input.search }, function() { console.log("setState completed", this.state) } )

esto puede ser útil