簡體   English   中英

節點js原型對象'self'變量未存儲正確的回調上下文

[英]node js prototype object 'self' var does not store correct context for callback

我是一位經驗豐富的開發人員,但是對Java腳本和Node.js還是陌生的,如果這個問題已按原樣回答,我深表歉意,但是即使我遍歷了多個示例和stackoverflow答案,也沒有找到原型類的簡單完整示例正確的'self'變量作用域和綁定(this)。 我都嘗試過,但都出錯了...感謝您的幫助。 我試着把var self = this; 在我的函數聲明的開頭,但是在運行時,將其設置為原型時,它實際上並沒有經過函數代碼,因此,“ this”未正確設置。

   /**
     * Module Dependencies
     */
    var cheerio = require('cheerio');
    var http = require('http');

    /**
     * Export
     */

    module.exports = SimplePageGetter;

    function SimplePageGetter(pageLink) {
        this._pageLink = pageLink;
    }

    SimplePageGetter.prototype.getPage = function () {
        var self = this;
        http.request(self._pageLink, self._resultsPageHttpGetCallback).end();
    };

    SimplePageGetter.prototype._resultsPageHttpGetCallback = function (response) {
        var pageBody = '';
        var self = this;
        //another chunk of data has been recieved, so append it to `str`
        response.on('data', function (chunk) {
            pageBody += chunk;
        });

        //the whole response has been recieved, so we just print it out here
        response.on('end', function () {
            self._parsePage(pageBody);
        });
    };

SimplePageGetter.prototype._parsePage = function (body) {
  console.log('page parsed');
}

出於某種原因,調用getPage時'self'是正確的,但它將是http模塊ClientRequest而不是_resultsPageHttpGetCallBack上的對象。 請問我做錯了什么?

謝謝 ,

詹姆士

設置self 調用函數中沒有做任何事情去改變什么this被稱為將是功能。 所以看這個:

SimplePageGetter.prototype.getPage = function () {
        var self = this;
        http.request(self._pageLink, self._resultsPageHttpGetCallback).end();
    };

那仍然只是將對self._resultsPageHttpGetCallback函數的引用傳遞給http.request http.request仍將其僅作為普通函數而不是方法來調用,因此_resultsPageHttpGetCallback this _resultsPageHttpGetCallback將是未定義的(嚴格模式)或全局對象(寬松的模式)。

self模式對於在同一作用域(或嵌套作用域)中創建的函數很有用,例如:

function someMethod() {
    var self = this;
    http.request(self._pageLink, function(err, data) {
        // Use `self` here to access object info
    }).end();
}

之所以http.request是因為我要傳遞給http.request的匿名函數關閉 (具有對它的創建上下文)的引用,並且該上下文具有self變量,因此該函數可以訪問self變量。

對於您正在做的事情, Function#bind會更合適:

SimplePageGetter.prototype.getPage = function () {
        http.request(this._pageLink, this._resultsPageHttpGetCallback.bind(this)).end();
    };

Function#bind創建一個函數,該函數在被調用時將調用此函數並將this設置為特定值。

有關this更多信息:


僅供參考,這是應用於完整代碼示例的Function#bind模式:

/**
 * Module Dependencies
 */
var cheerio = require('cheerio');
var http = require('http');

/**
 * Export
 */

module.exports = SimplePageGetter;

function SimplePageGetter(pageLink) {
    this._pageLink = pageLink;
}

SimplePageGetter.prototype.getPage = function () {
    http.request(this._pageLink, this._resultsPageHttpGetCallback.bind(this)).end();
};

SimplePageGetter.prototype._resultsPageHttpGetCallback = function (response) {
    var pageBody = '';

    response.on('data', function (chunk) {
        pageBody += chunk;
    });

    //the whole response has been recieved, so we just print it out here
    response.on('end', function () {
        this._parsePage(pageBody);
    }.bind(this));
};

SimplePageGetter.prototype._parsePage = function (body) {
    console.log('page parsed');
};

您可能會研究ES2015(也稱為ES6)的新功能,因為底層V8引擎支持它們,所以您現在可以從v4開始在NodeJS中使用其中的許多功能(或者,您可以使用轉譯器從ES6輸入生成ES5代碼)。

以下是使用ES2015的內容:

  • ...箭頭的功能,它繼承了this從他們定義中的背景下,使得self不必要的。

  • ... class關鍵字,它提供了一種更簡潔的編寫構造函數和原型的方法。

  • ... let關鍵字,只是因為它是ES2015代碼。 :-)

應用這些:

/**
 * Module Dependencies
 */
let cheerio = require('cheerio');
let http = require('http');

class SimplePageGetter {
    constructor(pageLink) {
        this._pageLink = pageLink;
    }

    getPage() {
        http.request(this._pageLink, response => {
            this._resultsPageHttpGetCallback(response);
        }).end();
    }

    _resultsPageHttpGetCallback(response) {
        let pageBody = '';

        response.on('data', chunk => {
            pageBody += chunk;
        });

        //the whole response has been recieved, so we just print it out here
        response.on('end', () => {
            this.parsePage(pageBody);
        });
    }

    _parsePage(body) {
        console.log('page parsed');
    }
}

/**
 * Export
 */

module.exports = SimplePageGetter;

請注意, class沒有像函數聲明那樣懸掛,因此導出的標准位置通常在模塊的底部。 但是,如果只有一個出口(如本例所示),則可以

module.exports = class SimplePageGetter {
    //...
};

最后但並非最不重要的一點:除非您真的需要_resultsPageHttpGetCallback_parsePage成為對象的屬性(它們是公共的),否則我可能會將它們設為私有函數,這些函數要么接受SimplePageGetter實例作為標准參數,要么期望被調用this指的是它,即使他們不是方法。

在這里,他們有一個論點:

/**
 * Module Dependencies
 */
let cheerio = require('cheerio');
let http = require('http');

class SimplePageGetter {
    constructor(pageLink) {
        this._pageLink = pageLink;
    }

    getPage() {
        http.request(this._pageLink, response => {
            resultsPageHttpGetCallback(this, response);
        }).end();
    }
}

function resultsPageHttpGetCallback(getter, response) {
    let pageBody = '';

    response.on('data', chunk => {
        pageBody += chunk;
    });

    //the whole response has been recieved, so we just print it out here
    response.on('end', () => {
        parsePage(getter, pageBody);
    });
}

function parsePage(getter, body) {
    console.log('page parsed');
}

/**
 * Export
 */

module.exports = SimplePageGetter;

在這里,他們希望設置this設置,因此我們通過Function#call對其進行Function#call

/**
 * Module Dependencies
 */
let cheerio = require('cheerio');
let http = require('http');

class SimplePageGetter {
    constructor(pageLink) {
        this._pageLink = pageLink;
    }

    getPage() {
        http.request(this._pageLink, response => {
            resultsPageHttpGetCallback.call(this, response);
        }).end();
    }
}

function resultsPageHttpGetCallback(response) {
    let pageBody = '';

    response.on('data', chunk => {
        pageBody += chunk;
    });

    //the whole response has been recieved, so we just print it out here
    response.on('end', () => {
        parsePage.call(this, pageBody);
    });
}

function parsePage(body) {
    console.log('page parsed');
}

/**
 * Export
 */

module.exports = SimplePageGetter;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM