与Electron-vue逐行异步读取文件

时间:2019-05-04 14:47:05

标签: electron electron-vue

我正在用Electron-vue进行开发。我想逐行读取用户提供的大文本文件。另外,我想在阅读过程中显示一个加载图标(这意味着阅读应该是异步的)。
请注意,该文本文件使用shift-jis编码。

起初,我尝试了以下方法:
src / renderer / components / Import.vue

const dialog = require('electron').remote.dialog
export default {
  name: 'import',
  data () {
    return {
      loading: false
    }
  },
  methods: {
    mounted () {
      this.$refs.search.focus()
    },
    openDialog () {
      let filePath = dialog.showOpenDialog({
        properties: ['openFile'],
      })
      this.loading = true
      let that = this
      // Use the async function.
      this.getResultFileRead(that, filePath[0]).then(function (res) {
        // When the async function is completed, remove the loading icon.
        that.loading = false
        console.log(res)
      })
    },
    // Define async function here.
    async getResultFileRead (path) {
      return this.$electron.ipcRenderer.sendSync('readfile', path)
    }
  }
}

src / main / index.js

import fs from 'fs'
import readline from 'readline'
import iconv from 'iconv-lite'

ipcMain.on('readfile', (event, arg) => {
  // Using stream to decode shift-jis file.
  stream = fs.createReadStream(filePath).pipe(iconv.decodeStream('shift-jis'))
  let reader = readline.createInterface(stream, {})
  reader.on('line', line => {
     insertLine(line)
  })
  reader.on('close', () => {
    // do other stuff
  })
  event.returnValue = 'complete'
})

但是这些没有用。提供文件时,将以异步方式读取文件,但是只要提供了文件(即在完成操作之前),readfile函数就会返回“ complete”,因此加载图标永远不会出现。

如何在Electron-Vue上实现“异步读取带有shift-jis的文件”和“读取文件时显示加载图标”两者? 请注意,Electron-vue似乎使用的是Node.js版本8.9.3。

1 个答案:

答案 0 :(得分:0)

我如下解决了这个问题。
src / main / index.js

import fs from 'fs'
import readline from 'readline'
import iconv from 'iconv-lite'

ipcMain.on('readfile', async (event, arg) => {
    await readLines()
    event.sender.send('readfile-reply', 'complete')
})

function readLines() {
    return new Promise((resolve, reject) => {
        stream = fs.createReadStream(filePath).pipe(iconv.decodeStream('shift-jis'))
        let reader = readline.createInterface(stream, {})
        reader
            .on('line', line => {
                insertLine(line)
            })
            .on('close', () => {
                resolve() // "Resolve" in the close event.
            })
            .on('error', function(err) {
                reject(err)
            })
    })
}

然后该函数可以异步使用:
src / renderer / components / Import.vue

const dialog = require('electron').remote.dialog
export default {
    name: 'import',
    data() {
        return {
            loading: false
        }
    },
    methods: {
        mounted() {
            this.$refs.search.focus()
        },
        openDialog() {
            let filePath = dialog.showOpenDialog({
                properties: ['openFile'],
            })
            this.loading = true
            let that = this
            // Use the async function.
            this.asyncReadFile(that, filePath[0]).then(function(res) {
                // When the async function is completed, remove the loading icon.
                that.loading = false
                console.log(res)
            })
        },
        asyncReadFile(that, path) {
            return new Promise(resolve => {
                this.$electron.ipcRenderer.send('readfile', path)
                this.$electron.ipcRenderer.on('readfile-reply', (event, result) => {
                    resolve(result)
                })
            })
        }
    }
}