一旦我从 Promise 中获得价值,就渲染 li 价值

Posted

技术标签:

【中文标题】一旦我从 Promise 中获得价值,就渲染 li 价值【英文标题】:Render li value once I got value from promise 【发布时间】:2020-02-23 16:51:32 【问题描述】:

我有一个呈现列表的模板。其中两个值需要进行地理编码(从我想显示地址的纬度值开始)。我在控制台中有值,但 li 显示 [object Promise]。我知道渲染不是同步的,所以我尝试使用一个标志来显示 li 仅当我有值时,但它们从未显示。基本上我了解问题所在,但无法弄清楚如何重新排列代码以使其正常工作。 这里是模板:

<div v-if="!isLoading && Object.keys(currentActivity).length > 0">
            <ul
              v-for="value in currentActivity"
              :key="value.id"
              class="listValues"
            >
              <li>Attività:
                <b> value.activity.activityName  -  value.related_activity 
                </b>
              </li>
              <li>Inizio: <b> value.start </b></li>
              <li>Fine: <b> value.end </b></li>
              <li>Durata: <b> timeConvert(value.duration) </b></li>
              <li v-if="!isGeocoding">Punto di partenza: <b> getAddress(getLatLng(value.starting_point)) </b></li>
              <li v-if="!isGeocoding">Punto di arrivo: <b> getAddress(getLatLng(value.arrival_point)) </b></li>
              <li>Stato: <b> value.status | stato </b></li>
              <li>Distanza: <b> kmCovert(value.travel_distance) </b></li>
              <li>Kcal consumate: <b> value.kcal </b></li>
              <li>Produzione di Co2: <b> value.co2 </b></li>
              <li>Costo: <b> value.cost  €</b></li>
              <li>Utente:
                <router-link :to="name: 'SchedaUtente', params:  userId: value.owner.id ">
                  <b style="text-decoration: underline;">
                     value.owner.username 
                  </b>
                </router-link>
              </li>
            </ul>
          </div>

我也尝试将条件放在 div 中(连同!isLoading &amp;&amp; Object.keys(currentActivity).length &gt; 0),但这样整个列表不会显示。 在我设置的数据中,除其他外,isGeocoding: true 涉及的其他方法:

async mounted() 
    await this.getActivityData()
  ,
  methods: 
    getActivityData() 
      this.isLoading = true
      const currentUser = this.$store.getters.currentProfile.user
      this.currentUser = currentUser
      console.log('current activity scheda attivita: ', this.currentActivity)
      console.log('current user scheda attivita: ', currentUser)
      this.isLoading = false
      console.log('is loading after ', this.isLoading)
    ,
    getLatLng(sridPoint) 
      const arrayLatLng = sridPoint.replace('SRID=4326;POINT (', '').replace(')', '').split(' ')
      const latLng =  lat: parseFloat(arrayLatLng[1]), lng: parseFloat(arrayLatLng[0]) 
      return latLng
    ,
    async getAddress(latLng) 
      await this.$gmapApiPromiseLazy().then(() => 
        const geocodeAddress = new Promise(function(resolve, reject) 
          // eslint-disable-next-line no-undef
          const geocoder = new google.maps.Geocoder()
          geocoder.geocode( 'location': latLng , function(results, status) 
            if (status === 'OK') 
              if (results.length > 0) 
                resolve([results[0].formatted_address])
              
             else 
              reject(new Error('Couldnt\'t find the location.'))
            
          )
        )
        geocodeAddress.then(function(address) 
          console.log(address)
          this.isGeocoding = false
          console.log('geocoding: ', this.isGeocoding)
          return address
        )
      )
    ,

这样两个地址永远不会显示,如果我删除标志 isGeocoding,正如我之前所说,我在控制台中得到了值,但在模板中得到了 [object Promise]。 有人可以帮忙吗? 谢谢 x

【问题讨论】:

如果你在退回之前console.log(address)会发生什么? 我得到了字符串地址,它应该在模板中。 【参考方案1】:

Vue 似乎不能很好地处理返回 Promise 的方法。

为了给你这个解决方法,我已经非常努力了:(你可以稍后感谢我:D)

创建一个组件并将其包含在每一行中,将方法输入传入内部,并让它进行计算:

演示:https://jsfiddle.net/niccord/rk1ec6au/

要点:

表:

<address-point :point="point"></address-point>

组件:

  methods: 
    getAddress() 
        return this.$gmapApiPromiseLazy().then(() => 
        // assign the value to the data variable! (this is when the trick happens)
        this.addr = this.point + 10
      )
    
  ,
  mounted () 
    // call the async method
    this.getAddress()
  

【讨论】:

感谢您抽出时间@niccord,但我设法以另一种方式解决了它。请参阅下面的解决方案。 x【参考方案2】:

这就是我的工作方式:

    我添加了响应式数据属性来表示起始地址和到达地址,并添加了另外两个 const 以获得更易读的代码,因此在数据中:
startingAddress: null,
arrivalAddress: null,
start: null,
end: null
    我在模板中引用了这些属性,而不是 Promise:
<li v-if="startingAddress">Punto di partenza: <b> this.startingAddress </b></li>
<li v-if="arrivalAddress">Punto di arrivo: <b> this.arrivalAddress </b></li>

通过这种方式,我可以摆脱布尔标志 isGeocoding,因为我可以简单地检查各个地址属性。

    然后我在 getActivityData 函数中调用了 getAddress 承诺,而不是从模板中调用。然后我可以响应这些承诺来设置相应的地址属性。
async getActivityData() 
      this.isLoading = true
      const currentUser = this.$store.getters.currentProfile.user
      this.currentUser = currentUser
      console.log('current activity scheda attivita: ', this.currentActivity)
      this.start = this.getLatLng(this.currentActivity.activity.starting_point)
      this.end = this.getLatLng(this.currentActivity.activity.arrival_point)

      console.log('PROMISE',this.getAddress(this.start))
      const [startingAddress, arrivalAddress] = await 
      Promise.all([this.getAddress(this.start), this.getAddress(this.end)])

      this.startingAddress = startingAddress
      this.arrivalAddress = arrivalAddress

      this.isLoading = false
    ,

我在mounted中调用了这个函数:

async mounted() 
  await this.getActivityData()
,
    我使其他两个函数更易于重用,如下所示:
getLatLng(sridPoint) 
   const arrayLatLng = sridPoint.replace('SRID=4326;POINT (', '').replace(')', '').split(' ')
   const latLng =  lat: parseFloat(arrayLatLng[1]), lng: parseFloat(arrayLatLng[0]) 
   return latLng
,
getAddress(latLng) 
   return this.$gmapApiPromiseLazy().then(() => 
   const geocodeAddress = new Promise(function(resolve, reject) 
     const geocoder = new google.maps.Geocoder()
     geocoder.geocode( 'location': latLng , (results, status) => 
       if (status === 'OK') 
         if (results.length > 0) 
           resolve(latLng = results[0].formatted_address)
          else 
           reject(new Error('Couldnt\'t find the location.'))
         
       
     )
   )   
   return geocodeAddress.then(function(address) 
     console.log(address)
     return address
   )
 )

请注意 getAddress 函数开头和结尾的两个 return,这是我之前遗漏的:

返回 this.$gmapApiPromiseLazy()....

返回地理编码地址....

x

【讨论】:

以上是关于一旦我从 Promise 中获得价值,就渲染 li 价值的主要内容,如果未能解决你的问题,请参考以下文章

如何从输入中获取价值?

ES6基础入门教程(十六)promise异步队列

css中一个li如何换行呢

获得承诺价值后返回可观察性

promise 的学习

Promise 对象