2016-03-04 6 views
2

Я разрабатываю скрипт PhantomJS для загрузки всех ресурсов веб-сайта и проверки их выполнения сценария bash.Как подождать PhantomJS 'fs.write, чтобы закончить запись

Для этого я написал метод page.onResourceReceived, когда я сохраняю файл с помощью fs.write(), а затем исполняю скрипт bash с помощью execFile().

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?

Update

Я также попытался это:

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); 
    } 
} 

Где ждать() является функцией, которая держит нить занят в течение X миллисекунд.

ответ

1

fs.write метод в PhantomJS doesn't seem иметь обратный вызов.

Просто добавьте немного таймаута, чтобы дать время ОС завершить запись на диск.

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); 

    } 
} 
+0

Благодарим вас за ответ. Я попробовал, но даже с задержкой, есть несколько ресурсов, которые не работают при выполнении сценария bash. Я попробую еще раз с большей задержкой, но я думаю, что должно быть лучшее исправление. –

+0

Тайм-ауты не являются эффективным способом достижения синхронизации/заказа в асинхронных вызовах и являются плохой практикой. – AxxE

0

Одним из способов решения этой проблемы является обернуть fs.write() вызов в функцию, которая возвращает объект Promise и продолжить exeFile() вызова после того, как вернулся Promise разрешен. Существует несколько библиотек JS, которые помогут вам сделать это явно. Я лично использую Q.

Альтернативный подход заключается в использовании Async.js. IMO, это помогает достичь более чистого, более читаемого и поддерживаемого кода/потока в нескольких сценариях (который может включать этот).

Promise подход описан кратко и Async.js основы объясняются в достаточной степени для начинающих here.

+0

Согласны, этот способ определенно лучше с точки зрения удобочитаемости и более поздней расширяемости. Пожалуйста, предоставьте образец кода для ситуации с использованием выбранной вами библиотеки. – Vaviloff

+1

Спасибо за ваш ответ и ссылки. Я ничего не знал о обещаниях. Но как бы Promise обнаружил, что выполняет обратный вызов? Я имею в виду, что метод fs.write() заканчивается, хотя файл фактически не существует.Возможно ли, что обратный вызов будет вызван только для завершения метода fs.write(), и это приведет к такому же поведению? –

Смежные вопросы