电子应用程序性能:使用ipcRenderer.sendSync阻止线程

时间:2018-03-30 16:46:26

标签: javascript reactjs electron

我有一个用Electron构建的音乐播放器。

我正在进行一些我没想到的性能/进程阻塞。我正在尝试为繁重的IO操作做一些后台进程。 (确定歌曲持续时间和专辑封面)

我这样做是通过electron.remote模块调用方法。 我注意到应用程序没有以某种方式异步地执行这些操作。

我一直在运行性能工具来检查并看到点击处理程序耗费了大量时间。

the click handler

深入挖掘我发现ipcRenderer.sendSync被调用。

enter image description here

Electron Docs中有关于sendSync阻止性质的警告。但是,我自己的代码不会调用它。所以我怀疑代码中的远程模块或其他东西会导致调用sendSync

整个应用代码都在Github上,但here is an example of electron.remote usage

要点是这样的:

import {remote} from 'electron'

const fs = remote.require('fs')
const mm = remote.require('musicmetadata')

// read song file, IO
function readMetadata (filePath) {
  return new Promise(function (resolve, reject) {
    const stream = fs.createReadStream(filePath)
    mm(stream, {duration: true}, function (err, metadata) {
      // ...
    })
  })
}

// get metadata for an array of songs
async function refreshSongsDuration (songs) {
  const songsMetadata = await Promise.all(songs.map((song) => readMetadata(song.filePath)))

  return songs.map((song, index) => {
    song.duration = songsMetadata[index].duration
    return song
  })
}

然后在点击处理程序中我会有这样的事情:

playArtist (artistID) {
  const songs = this.library.getArtistSongs(artistID)
  this.playlist.setSongs(songs)
  musicPlayer.play()

  const shouldGetDuration = songs.some((song) => song.duration === 0)

  // This is expected to be asynchronous and non blocking.
  if (shouldGetDuration) {
    mediaLibrary.refreshSongsDuration(songs)
      .then((updatedSongs) => {
        this.playlist.set('songs', updatedSongs)
      })
  }
}

所以,我想这里的一个简单问题是,我做错了什么导致这些阻塞过程?

1 个答案:

答案 0 :(得分:0)

https://github.com/electron/electron/blob/master/docs/api/remote.md#remote-objects

  

远程模块返回的每个对象(包括函数)表示主进程中的对象(我们将其称为远程对象或远程函数)。当您调用远程对象的方法,调用远程函数或使用远程构造函数(函数)创建新对象时,您实际上是在发送同步进程间消息。

每个远程模块本质上都是同步的。