0

我有一个 nativescript vue 应用程序,在某个页面上,我需要使用 axios 从 api 获取一些数据(每 3 秒)。数据以 xml 形式返回,我使用 xml2js 将其转换为 json。我对这两个功能都使用了 async/await。有东西阻塞了 UI 线程,因为每当这个函数运行时,我的应用程序中的滚动以及任何动画都会冻结。

有谁知道这里是什么阻塞了 DOM?

<template>
  //ui code here
</template>

<script>
import { mapGetters } from 'vuex'
import axios from 'axios'
import xml2js  from 'nativescript-xml2js'

export default {
  name: 'component1',
  data () {
    return {
      pending: true,
      error: false,
      results: null,
      refreshInterval: null
    }
  },
  computed: {
    ...mapGetters({
      token: 'main/token'
    })
  },
  methods: {
    async requestData() {

      const headers = {
        Cookie: 'USER_ID=' + this.token
      }
      const url = 'url goes here'
      const parser = new xml2js.Parser({
        async: true
      })

      try {
        const response = await axios.get(url, { headers: headers })

        const newData = await new Promise((resolve, reject) => parser.parseString(response.data, (err, result) => {
          if (err) reject(err)
          else resolve(result)
        }))

        this.results = newData['results']
        this.error = false
        this.pending = false

      } catch (e) {
        this.data = null
        this.error = e
        this.pending = false
      }
      this.pending = false
    }
  },
  created() {
    setTimeout(() => {
      this.requestData()
    },500)
    this.refreshInterval = setInterval(() => {
      this.requestData()
    },3000)
  },
  beforeDestroy () {
    clearInterval(this.refreshInterval)
  }
}
</script>

编辑: 我尝试实现工人将 xml2js 卸载到另一个线程,但仍然有同样的问题。这就是我的代码现在的样子:

家.vue:

<template>
<template/>

<script>
import { mapGetters } from 'vuex'

export default {
  name: 'component1',
  data () {
    return {
      dataLoaded: true,
      error: false,
      results: null,
      refreshInterval: null
    }
  },
  computed: {
    ...mapGetters({
      token: 'main/token'
    })
  },
  methods: {
    requestData() {

      console.log('fetching....')

      this.$backendService
        .api()
        .then(xml => {
          return this.$backendService.x2jworker(xml)
        })
        .then(json => {
          if( this.results !== json['results'] ) {
            this.results  = json['results']
          }
          this.dataLoaded = true
          this.error = false
        })
        .catch((error) => {
          this.dataLoaded = true
          this.error = true
        })
    }
  },
  created() {
    setTimeout(() => {
      this.requestData()
    },500)
    this.refreshInterval = setInterval(() => {
      this.requestData()
    },3000)
  },
  beforeDestroy () {
    clearInterval(this.refreshInterval)
  }
}
</script>

后端服务.js:

import axios from 'axios';
import xml2js from 'nativescript-xml2js'
import { WorkerService } from "../worker.service"

export default class BackendService {

  api() {
    return new Promise((resolve, reject) => {
      const url = 'url'
      axios.get(url)
        .then(response => {
          resolve(response.data)
        })
        .catch((error) => {
          if (error) {
            console.log('uh oh')
            reject(error)
          }
        })
    })
  }

  x2jworker(xml) {
    return new Promise((resolve, reject) => {
      var workerService = new WorkerService()
      var jsWorker = workerService.initJsWorker()
      jsWorker.onmessage = m => {
        resolve(m.data)
      }
      jsWorker.postMessage(xml)
      jsWorker.onerror = e => {
        console.log(e)
        jsWorker.terminate()
        reject(e)
      }
    })
  }
}

工人/javascript.worker.js:

import 'tns-core-modules/globals'
import xml2js  from 'nativescript-xml2js'

global.onmessage = function (msg) {
    console.log("Inside JS worker...")
    var parser = new xml2js.Parser({
      async: true
    })

    parser.parseString(msg.data, function (err, result) {
      if (err) {
        console.log(err)
        global.close()
      } else {          
        global.postMessage(result)
      }
    })
}

工人服务.js:

const workers = []

export class WorkerService {
  constructor() {
  }

  initJsWorker() {
    if (this.jsWorker) {
      return this.jsWorker
    }

    const JsWorker = require("nativescript-worker-loader!./workers/javascript.worker.js")
    this.jsWorker = new JsWorker()
    workers.push(this.jsWorker)

    return this.jsWorker
  }
}

if ((module).hot) {
  (module).hot.dispose(() => {
    workers.forEach(w => {
      w.terminate()
    })
  })
}
4

0 回答 0