如何等待PhantomJS的fs.write完成写作

时间:2016-03-04 11:58:40

标签: javascript asynchronous file-io phantomjs

我正在开发一个PhantomJS脚本来下载网站的所有资源并测试它们执行bash脚本。

为此,我在使用fs.write()保存文件时编写了page.onResourceReceived方法,然后使用execFile()执行bash脚本。

page.onResourceReceived = function(resource) {
    if (resource.stage == 'end') {
        fileName = getFileNameFromURL(resource.url);
        fs.write('files/' + fileName, resource.body, 'wb');
        execFile('sh', [SH_PATH, 'files/' + fileName], null, null);
    }
}

(这不是整个onResourceReceived代码)

如果我为execFile配置回调,它会抛出一个没有这样的文件或目录错误,但是,我检查目录和文件是否存在。

我认为这可能是同步问题。

  1. fs.write是异步方法吗?

  2. 有同步执行fs.write和execFile方法的替代方法吗?

  3. 更新

    我也试过这个:

    function waitForFile(filePath, attempts) {
        var fileExists = false;
        var i = 0;
        while (!fileExists && i < attempts) {
            wait(50);
            fileExists = fs.exists(filePath) && fs.isFile(filePath) && fs.size(filePath) > 0;
            i++;
        }
    }
    
    page.onResourceReceived = function(resource) {
        if (resource.stage == 'end') {
            fileName = getFileNameFromURL(resource.url);
            fs.write('files/' + fileName, resource.body, 'wb');
            waitForFile('files/' + fileName, 5);
            execFile('sh', [SH_PATH, 'files/' + fileName], null, null);
        }
    }
    

    其中wait()是一个在X毫秒内保持线程忙的函数。

2 个答案:

答案 0 :(得分:1)

PhantomJS doesn't seem中的

fs.write方法可以进行回调。

只需添加一点超时即可让操作系统有时间完成写入磁盘。

page.onResourceReceived = function(resource) {
    if (resource.stage == 'end') {
        fileName = getFileNameFromURL(resource.url);
        fs.write('files/' + fileName, resource.body, 'wb');

        setTimeout(function(){
            execFile('sh', [SH_PATH, 'files/' + fileName], null, null);
        }, 500);

    }
}

答案 1 :(得分:0)

解决此问题的一种方法是将fs.write()调用包装在一个返回Promise对象的函数中,并在返回exeFile()后返回Promise调用解决。有几个JS库可以帮助您明确地执行此操作。我个人使用Q

另一种方法是使用Async.js。 IMO,这有助于在几种情况下(包括这种情况)实现更清晰,更易读和可维护的代码/流程。

简要介绍了Promise方法,并为初学者here充分解释了 Async.js 要点。