6

server.listen(...)PhantomJSから使用しています。これは主に実験的なものであり、本番環境では使用しないでください。私はそれを単純なスクリーンショットに使用しています-受け入れるサーバーはURLのスクリーンショットを生成します。これは、PhantomJSで遊ぶために使用しているおもちゃのプロジェクトです。response特に、オブジェクトが使用できない、長時間実行されるリクエストの問題に気づきました。これが私のコードからの関連するスニペットです:

var service = server.listen(8080, function (request, response) {

    response.statusCode = 200;

    if (loglevel === level.VERBOSE) {
        log(request);
    } else {
        console.log("Incoming request with querystring:", request.url);
    }

    var params = parseQueryString(request.url);
    if (params[screenshotOptions.ACTION] === action.SCREENSHOT) {
        getScreenshot(params, function (screenshot) {

            response.headers["success"] = screenshot.success; //<-- here is where I get the error that response.headers is unavailable. Execution pretty much stops at that point for that particular request.
            response.headers["message"] = screenshot.message;

            if (screenshot.success) {
                response.write(screenshot.base64);
            } else {
                response.write("<html><body>There were errors!<br /><br />");
                response.write(screenshot.message.replace(/\n/g, "<br />"));
                response.write("</body></html>");
            }

            response.close();
        });
    } else {
        response.write("<html><body><h1>Welcome to the screenshot server!</h1></body></html>")   
        response.close();
    }
});

getScreenshotWebPage.open(...)関数を使用してWebページを開く非同期メソッドです。この関数も非同期です。したがって、発生しているように見えるのは、引数として渡されたコールバックgetScreenshotが最終的に呼び出されたときに、responseオブジェクトがすでに削除されているように見えることです。基本的に、PhantomJSから次のエラーが発生します。

Error: cannot access member `headers' of deleted QObject

これは、リクエストがタイムアウトして接続が閉じられたためだと思います。response.write("")ドキュメントには、接続を開いたままにするために少なくとも1回呼び出すことが記載されています。私response.write("")は最初に電話をかけてみましたが、500ミリ秒ごとに実行してserver.listen(...)いたかなりハッキーなソリューションも試しました(50ミリ秒まで下げました)。また、終わったら必ずインターバルをクリアしました。しかし、私はまだこの問題を抱えているようです。setInterval(...)response.write("")

これは、Webサーバーモジュールがより堅牢になるまで対処しなければならないことですか?それともそれを回避する方法はありますか?

4

2 に答える 2

8

私はこれを理解することができました。WebPage.open(たとえばhttp://fark.comと)を含む特定のページをロードしているときに、http://cnn.com複数のonLoadFinishedイベントが発生したようです。これにより、コールバックがWebPage.open複数回呼び出されます。つまり、制御が呼び出し元の関数に戻ったときに、応答をすでに閉じているため、responseオブジェクトは無効になります。WebPage.open関数が呼び出される前にフラグを作成することでこれを修正しました。onLoadFinishedコールバック内で、フラグのステータスをチェックして、前のイベントがすでに発生しているかどうかを確認します。コールバック内で行う必要があることをすべて実行したらWebPage.open、フラグを更新して、処理が終了したことを示します。このようにして、(少なくとも私のコードのコンテキストでは)偽のonLoadFinishedイベントは処理されなくなります。

于 2012-07-22T18:41:27.477 に答える
0

(以下はPhantomJS 1.9.7を参照していますが、OPは1.6.1以前を参照している可能性が高いことに注意してください。)

複数のイベントが発生している場合は、自分で聞く代わりにonLoadFinished使用できます。を使用すると、ハンドラーがプライベートハンドラーでラップされ、コールバックが1回だけ呼び出されるようになります。page.open()onLoadFinishedpage.open()

ソースから:

definePageSignalHandler(page, handlers, "_onPageOpenFinished", "loadFinished");
page.open = function (url, arg1, arg2, arg3, arg4) {
    var thisPage = this;
    if (arguments.length === 1) {
        this.openUrl(url, 'get', this.settings);
        return;
    }
    else if (arguments.length === 2 && typeof arg1 === 'function') {
        this._onPageOpenFinished = function() {
            thisPage._onPageOpenFinished = null;
            arg1.apply(thisPage, arguments);
        }
        this.openUrl(url, 'get', this.settings);
        return;
    }
// ... Truncated for brevity

この機能は、公式APIの一部として公開されている、他の回答とまったく同じです。

于 2014-05-29T01:30:46.867 に答える