如何在phantomjs中实现快速,可查询和持久的数据库?

Sur*_*ran 2 sqlite node.js phantomjs browserify

我一直在使用phantomjs在服务器端dom环境中为我做一些繁重的工作.直到现在我一直把数据结构放在内存中(即对它们没什么特别的),一切都很好.但最近在一些用例中我开始遇到以下问题:

  1. 内存使用率变得太高,导致交换启动并严重影响我的性能.
  2. 无法从上一个保存点恢复,因为内存中的数据结构不是持久的(显然)

这迫使我寻找一个用于幻像的数据库解决方案,但在决定解决方案时我又遇到了问题:

  1. 我不希望我的表演太受影响.
  2. 它必须是持久的和可查询的
  3. 我怎么能从幻像脚本里面连接数据库.

谁能引导我找到满意的解决方案?

注意:我几乎已经决定,sqlite但从幻影连接到它仍然是一个问题.Nodejs提供sqlite3节点模块,我正在尝试browserify使用幻像.

注意注意: Browserify没有用!回到地面零!:-(

Thanx提前!

Ebo*_*alm 9

Phantomjs的文件系统API允许您读取和写入二进制文件:

buf = fs.read(FILENAME, 'b') and
fs.write(FILENAME, buf, 'b')
Run Code Online (Sandbox Code Playgroud)

sql.js(https://github.com/kripken/sql.js/)为您提供了一个可以在phantomjs中运行的JavaScript SQLite实现.

结合2,您就拥有了一个快速,持久,可查询的SQL数据库.

示例演练

  1. 获取javascript SQLite实现(保存到/tmp/sql.js)

    $ wget https://raw.githubusercontent.com/kripken/sql.js/master/js/sql.js -O /tmp/sql.js

  2. 使用命令行sqlite3应用程序创建一个测试SQLite数据库(显示它是持久的并且在phantomjs应用程序外部).

    sqlite3 /tmp/eg.db

    sqlite> CREATE TABLE IF NOT EXISTS test(id INTEGER PRIMARY KEY AUTOINCREMENT,创建INTEGER NOT NULL DEFAULT CURRENT_TIMESTAMP);

    sqlite> .quit

  3. 保存此测试phantomjs脚本以将条目添加到测试数据库并验证行为.

$ cat /tmp/eg.js

var fs = require('fs'),
    sqlite3 = require('./sql.js'),                                                                    
    dbfile = '/tmp/eg.db', 
    sql = 'INSERT INTO test(id) VALUES (NULL)', 
    // fs.read returns binary 'string' (not 'String' or 'Uint8Array')
    read = fs.read(dbfile, 'b'), 
    // Database argument must be a 'string' (binary) not 'Uint8Array'
    db = new sqlite3.Database(read),              
    write,
    uint8array;                                                                                       

try {   
    db.run(sql);
} catch (e) {
    console.error('ERROR: ' + e);                                                                     
    phantom.exit();                                                                                   
}

// db.export() returns 'Uint8Array' but we must pass binary 'string' to write
uint8array = db.export(); 
write = String.fromCharCode.apply(null, Array.prototype.slice.apply(uint8array));                     

fs.write(dbfile, write, 'b');                                                                         
db.close();                                                                                           

phantom.exit();
Run Code Online (Sandbox Code Playgroud)
  1. 运行phantomjs脚本进行测试

    $ /usr/local/phantomjs-2.0.0-macosx/bin/phantomjs /tmp/eg.js

  2. 使用外部工具验证更改是否持久.

    sqlite3 /tmp/eg.db

    sqlite> SELECT*FROM test;

    id已创建

    1 2015-03-28 10:21:09

    sqlite的>

要注意的一些事项:

  1. 仅当您调用fs.write时,才会在磁盘上修改数据库.在您调用fs.write之前,您所做的任何更改对访问同一SQLite数据库文件的外部程序都是不可见的.
  2. 使用fs.read将整个数据库读入内存.您可能希望为不同的表(或表的版本)提供不同的OS文件,具体取决于您的应用程序和表中的数据量,以满足您提到的内存要求.
  3. 将sqlite3.export()返回的内容传递给fs.write会破坏磁盘上的SQLite数据库文件(它将不再是有效的SQLite数据库文件).Uint8Array不是fs.write参数的正确类型.