2016-03-07 4 views
0

хорошо мой код что-то вроде этого только несколько строкphantomjs не делает веб-страницы в детские

var a = "http://lnmtl.com/chapter/renegade-immortal-chapter-"; 
var b = 558; 
var d = "rennegrade_ch"; 
var f = ".png"; 
var page = require('webpage').create(); 
var i = 0; 
for (i = b; i < 560; i++) { 
    var c = a + i; 
    console.log(c); 
    page.open(c, function() { 
     var e = d + i + f; 
     console.log(e); 
     page.render(e); 

    }); 
} 
phantom.exit(); 

веб-страница может быть предоставлена ​​по отдельности, но когда я положил его в цикл все это делает печать первый вывод на консоль правильно, но второй он пропускает, я думаю, что он не входит в функцию page.open, а затем для увеличения значения цикла, то же самое происходит снова. Я понятия не имею, почему его не вводить функцию отображения. Я попытался установить var page = require ('webpage'). .Создайте(); внутри для цикла тоже, но до сих пор никаких изменений

UPDATE: На другой вопрос stackoverflow.com/questions/31621577/png-is-not-being-rendered-using-phantomjs-with-multiple-attempts-in-a- loop? rq = 1 было указано, что этот метод не работает из-за асинхронного характера функции, но код кода, представленный в нем, не является достаточно полезным, может кто-нибудь пример, и я также попробовал установить таймаут, как было предложено в нем, все равно происходит то же самое, идея?

+0

Что именно является проблема с Предложенное решение в [мой ответ] (http://stackoverflow.com/a/31625166/1816580) на связанный вопрос? В вашем коде представлены проблемы 2 и 3, которые я описал. –

+0

ah m извините, что рекурсивная часть и переменная статуса смутили меня там, моя ошибка, но я могу дать пример с установленным временем, я попробовал, но он не работал –

ответ

0

Для асинхронного запроса внутри цикла вы должны использовать асинхронную библиотеку, так что вы можете отлаживать код и не получить проблему утечки памяти

async-js будет хорошо в вашем случае

npm install async

var async = require('async'); 
var a = "http://lnmtl.com/chapter/renegade-immortal-chapter-"; 
var b = 558; 
var d = "rennegrade_ch"; 
var f = ".png"; 
var page = require('webpage').create(); 
var i = 0; 
async.whilst(
    function() { 
    return i < 560; 
    }, 
    function(callback) { 
    i++; 
    var c = a + i; 
    console.log(c); 
    page.open(c, function() { 
     var e = d + i + f; 
     console.log(e); 
     page.render(e); 
     callback(null, i); 
    }); 
    }, 
    function(err, n) { 
    if(err) console.log(err); 
    phantom.exit(); 
    }); 
1

Ваш phantom.exit() вызов убивает браузер PhantomJS, прежде чем выполнять рендеринг. Вы должны дождаться завершения рендеринга, прежде чем сможете exit(). Вы должны иметь некоторый механизм, чтобы сказать, когда рендеринг сделан. Я бы предложил обернуть каждый из ваших рендеров в Promise. Затем используйте Promise.all(), чтобы дождаться решения всех обещаний рендеринга. После того, как они разрешат, выйдите из PhantomJS.


Прямо сейчас, у вас есть то, что ниже, который не уважает асинхронную природу page.open():

for (...) { 
    // I probably wont finish because phantom dies almost immediately 
    page.open(c, function() { 
     // I won't finish running since phantom dies 
     page.render(e); 
    }); 
} 
// I'm going to kill the phantom almost immediately 
phantom.exit(); 

Вы хотите что-то вроде кода ниже, который будет ждать все делает, чтобы закончить , Это будет размещать каждый из сайтов, которые мы предоставляем, в подкаталоге «рендеринг».

Примечание: Для этого необходимо установить прокладку es6-promise, так как PhantomJS пока не поддерживает Promises. Спасибо за the comment об этом Artjon B

/*jslint node:true*/ 
/*globals phantom, sayHello*/ 

"use strict"; 

var Promise = require("es6-Promise").Promise; 

// Array of URLs that we want to render 
var urlArr = [ 
    { 
     name: "google", 
     url: "http://www.google.com" 
    }, 
    { 
     name: "yahoo", 
     url: "http://www.yahoo.com" 
    }, 
    { 
     name: "bing", 
     url: "http://www.bing.com" 
    } 
]; 

// Map URLs to promises 
var proms = urlArr.map(function (url) { 
    // Return a promise for each URL 
    return new Promise(function (resolve, reject) { 
     // Make a page 
     var page = require("webpage").create(); 
     // Open the URL 
     console.log("opening: " + url.name); 
     page.open(url.url, function() { 
      // Render the page 
      page.render("render/" + url.name + ".png"); 
      console.log("done rendering: " + url.name); 
      // Say that we are done with rendering 
      resolve(); 
     }); 
    }); 
}); 

// Wait for all rendering to finish 
Promise.all(proms).then(function() { 
    console.log("closing phantom"); 
    // Exit phantom 
    phantom.exit(); 
}); 
+1

PhantomJS не поддерживает обещания (проверено с помощью PhantomJS 2.1.1 и 1.9.8). Вам понадобится прокладка. –

+0

@ArtjomB. Спасибо, Artjom, исправил код, чтобы использовать es6-обещание. Это работает на моем клиенте. – zero298

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