1

我是 Sinatra 和网络编程的新手,所以使用的一些术语可能不太正确。反正...

我有一个应用程序将 .txt 逐行读取到数组中,然后当您加载 index.html.erb 时,它会随机显示其中一行。我将内容放在文本文件中,而不是直接放入数组中,这样如果我需要添加更多数据,则更容易更新,然后直接添加到数组中并重新部署应用程序。我担心的是它是否在每次加载页面时重新创建数组并重新读取文件。我不知道这种东西在服务器端是如何工作的,或者如何检查它。创建数组的代码如下:

before do
  @ways ||= ['']
  if @ways[1].nil?
    File.open('ways.txt', 'r').each_line { |line| @ways << line }
  end
end

然后我的路线:

get '/' do
  @way = @ways.sample

  erb :index
end

有没有办法确保这尽可能高效?还是应该完全以其他方式完成?根据 Chrome 开发工具,每页加载传输约 800b。

4

1 回答 1

4

您在此处编写的内容确实会在每次请求时将文件读入数组。

提示:您可以使用@ways = File.readlines('ways.txt')

如果你想缓存这个数组,你可以在应用程序启动时将其作为一个常量,例如:

WAYS = File.readlines('ways.txt').map(&:chomp)
get "/" do
  @way = WAYS.sample
  erb :index
end

但是,如果您编辑了文本文件,则需要退出并重新启动服务器。如果您想避免这种情况,您可以在before操作中检查文件的修改时间,并且仅在内容发生更改时才更新数组 ( replaceit)。

如果您在最后一个建议方面需要帮助,请告诉我,我可以根据需要进行编辑。


编辑:这是使用常量保存数据并仅在文件更改时重新加载的一种方法:

WAYS = { file:'ways.txt', all:[] }
before do
  if WAYS[:updated] != (mtime=File.mtime(WAYS[:file]))
    WAYS[:all].replace File.readlines(WAYS[:file]).map(&:chomp)
    WAYS[:updated] = mtime
  end
end
get "/" do
  @way = WAYS[:all].sample
  erb :index
end

这有点激进——检查每个请求的文件修改时间——但是除了最重的负载或最慢的磁盘之外,性能应该没问题。

另一种解决方案是每隔几分钟启动一个线程以强制检查/更新数组,例如

require 'sinatra'

WAYS = { file:'ways.txt', all:[] }
Thread.new do
  loop do
    if WAYS[:updated] != (mtime= File.mtime(WAYS[:file]))
      WAYS[:all].replace File.readlines(WAYS[:file]).map(&:chomp)
      WAYS[:updated] = mtime
    end
    sleep 5 # seconds
  end
end

get '/' do
  WAYS[:all].sample
end
于 2012-05-23T21:26:17.397 回答