使用 Electron-vue 逐行异步读取文件
Asynchronously read a file line by line with 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 函数 returns 'complete' 一旦文件被提供(即在完成操作之前),所以加载图标永远不会出现。
如何在 electron-vue 上同时实现 "read file with shift-jis asynchronously" 和 "showing loading icon while the file is being read"?
请注意,Electron-vue 似乎使用的是 Node.js 版本 8.9.3.
我解决了这个问题如下。重点是close事件中的resolve函数
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)
that.$electron.ipcRenderer.removeAllListeners('readfile-reply')
})
},
asyncReadFile(that, path) {
return new Promise(resolve => {
this.$electron.ipcRenderer.send('readfile', path)
this.$electron.ipcRenderer.on('readfile-reply', (event, result) => {
resolve(result)
})
})
}
}
}
我正在使用 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 函数 returns 'complete' 一旦文件被提供(即在完成操作之前),所以加载图标永远不会出现。
如何在 electron-vue 上同时实现 "read file with shift-jis asynchronously" 和 "showing loading icon while the file is being read"? 请注意,Electron-vue 似乎使用的是 Node.js 版本 8.9.3.
我解决了这个问题如下。重点是close事件中的resolve函数
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)
that.$electron.ipcRenderer.removeAllListeners('readfile-reply')
})
},
asyncReadFile(that, path) {
return new Promise(resolve => {
this.$electron.ipcRenderer.send('readfile', path)
this.$electron.ipcRenderer.on('readfile-reply', (event, result) => {
resolve(result)
})
})
}
}
}