[英]Race condition when calling components
I have 2 components which are being loaded into an "App", the first component resolves the external ip address to a geo by making 2 axios.get calls and then returns them (via emit) to App.vue.我有 2 个组件正在加载到“应用程序”中,第一个组件通过进行 2 个 axios.get 调用将外部 IP 地址解析为地理,然后将它们(通过发射)返回到 App.vue。
I then call "Weather" to resolve the lat/long from the previous 2 calls to some json returned by the darksky API for that lat/long.然后我调用“天气”来解析前 2 次调用中的纬度/经度,解析为该经度/经度的 Darksky API 返回的一些 json。 Sometimes (50-60% of the time) I am hitting a race condition where I am sending 0/0 to weather (which are what I initialize lat/long to in App.vue) and don't know how to resolve it.
有时(50-60% 的时间)我遇到了一个竞争条件,我将 0/0 发送到天气(这是我在 App.vue 中初始化纬度/经度的值)并且不知道如何解决它。 I would like the following code to run more reliably.
我希望以下代码能够更可靠地运行。
App.vue应用程序
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<ip @response="onResponse" /> //Needs to finish before next line runs (has axios calls)
<Weather msg="The weather for:" :lat="lat" :long="long" :ip="ip" :city="city" :country="country"/>
</div>
</template>
<script>
import Weather from './components/Weather.vue'
import ip from './components/ip_resolve.vue'
export default {
name: 'App',
data() {
return {
lat: 0,
long: 0,
ip: 0,
country: 0,
city: 0
}
},
components: {
Weather,
ip
},
//Accepts emitted values from ip_resolve -- needs to change values in data before Weather runs
methods: {
onResponse(event) {
this.lat = event.lat
this.long = event.long
this.ip = event.ip
this.country = event.country
this.city = event.city
}
}
}
</script>
ip_resolve.vue ip_resolve.vue
<template>
<div class="Hemlo">
</div>
</template>
<script>
const axios = require('axios').default;
const ipRegex = /ip=(\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3})$/gmi
export default {
name: 'ip',
props:{
ip: String,
country: String,
City: String,
lat: Number,
long: Number
},
mounted () {
axios.get('https://www.cloudflare.com/cdn-cgi/trace')
.then(response => (
this.ip = ipRegex.exec(response.data)[1]
)
.then(
axios.get('https://cors-anywhere.herokuapp.com/http://api.ipstack.com/'+this.ip+'?access_key=<key>')
.then( response => (
this.lat = response.data.latitude,
this.long = response.data.longitude,
this.country = response.data.country_name,
this.city = response.data.city
).then(
this.$emit('response', {
ip: this.ip,
lat: this.lat,
long: this.long,
country: this.country,
city: this.city
})
)
)
)
)
}
}
</script>
Weather.vue天气.vue
<template>
<div class="Hi">
<h1>{{msg}} {{city}}, {{country}}</h1>
<h2>Temp: {{ temp }}f</h2>
<h2>Conditions: {{ conditions }}</h2>
</div>
</template>
<script>
const axios = require('axios').default;
export default {
name: 'Weather',
props: {
msg: String,
resp: String,
ip: String,
lat: Number,
long: Number,
city: String,
country: String,
temp: String,
conditions: String
},
mounted () {
axios
.get('https://cors-anywhere.herokuapp.com/https://api.darksky.net/forecast/<key>/'+this.lat+','+this.long)
.then(response => (
this.resp = response.data,
this.temp = response.data.currently.temperature,
this.conditions = response.data.currently.summary
))
}
}
</script>
Typically you would separate out this model logic into its own module, using something like vuex, so the data flow for components is completely uni-directional.通常,您会使用 vuex 之类的东西将这个模型逻辑分离到它自己的模块中,因此组件的数据流是完全单向的。
But in this case, the simplest solution is to add a v-if="responseReady"
directive to the <Weather>
component in App.vue so that it does not get mounted until the data is ready.但在这种情况下,最简单的解决方案是在 App.vue 中的
<Weather>
组件中添加一个v-if="responseReady"
指令,以便在数据准备好之前不会挂载。 You will also need to add a boolean flag for this new prop to data
and onResponse
.您还需要为这个新道具添加一个布尔标志到
data
和onResponse
。 Again, this is the quick and dirty solution.同样,这是快速而肮脏的解决方案。
<Weather v-if="responseReady" msg="The weather for:" :lat="lat" :long="long" :ip="ip" :city="city" :country="country"/>
...
data() {
return {
lat: 0,
long: 0,
ip: 0,
country: 0,
city: 0,
responseReady: false
}
},
...
onResponse(event) {
this.lat = event.lat
this.long = event.long
this.ip = event.ip
this.country = event.country
this.city = event.city
this.responseReady = true;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.