返回使用.apply()调用的函数时从回调更新'this'

时间:2016-01-06 19:18:59

标签: javascript node.js

我有一个ProjectClient类,其中包含用于进行HTTP调用的方法(.GET())。它以与相同的方式支持一些参数和回调,但是在幕后也有一些复杂的url和header构建函数:

client.GET(idOrDataObject, function(err, customResponse) {
    // url is built based on the id or dataObject passed as the first param
})

成功回复后,返回的对象类型之一是DataObject

client.GET(idOrDataObject, function(err, customResponse) {
    console.log(customResponse.dataObject instanceof DataObject) // true
})

我正在为名为DataObject的{​​{1}}类添加一个便捷方法,该类回调reload()方法并重新加载,但我希望能够更新{ {1}}使用从服务器返回的新版client.GET()

this

用法如下:

DataObject

更新

开始认为这将起作用的唯一方法是,如果我在链中进一步劫持回调,例如在DataObject.prototype.reload = function() { var args = Array.prototype.slice.call(arguments) // extracts all arguments var client = helpers.client.validate(args) // ensures 'client' was passed in the args array before continuing args.unshift(this) // prepends 'this' (the DataObject instance) // How can I update 'this' with the response contained in the // callback passed (the last element in 'args')? return client.GET.apply(client, args) } 内:

client.GET(idOrDataObject, function(err, customResponse) {
    var o = customResponse.dataObject
    // assume something changed on the server
    o.reload(function(err, done) {
         // o has now been updated with the latest copy from the server
    })
})

但即使这样做,client.GET的原始副本也没有被更新 - 就像它被克隆或重复一样,并不是指向原始文件的指针?

这是一项证明失败的测试。如何确保传递到var DataObject = require('../lib/dataObject') var request = require('request') var _ = require('lodash') var GET = function(client, args) { var options = { client: client } // if a preformatted options argument passed, assign it to options if (_.isObject(args[0]) && !_.isFunction(args[0]) && args.length <= 2) { _.assign(options, args[0]) } options.callback = helpers.cb(_.last(args.filter(_.isFunction))) options.type = _.first([options.type, args[0]._type, args[0]].filter(_.isString)) options.dataObject = _.first([options.dataObject, args[0]].filter(function(property) { return (property instanceof DataObject) })) request('http://...', { body: options.body, json: true, method: 'GET' }, function(error, response) { var customResponse = new CustomResponse(response) if (options.dataObject instanceof DataObject) { options.dataObject = customResponse.dataObject // here I see both 'options.dataObject' and 'customResponse.dataObject' have the correct value for reloadTest console.log('updated', options.dataObject.reloadTest, customResponse.dataObject.reloadTest) } options.callback(error, customResponse, customResponse.dataObject) }) } 的正确指针?

dataObject

1 个答案:

答案 0 :(得分:1)

简短的回答是,你做不到。您实际上无法将对象替换为另一个对象。一些选择:

  • 使用包装器对象,并赋予reload方法:

    client.GET(idOrDataObject, function(err, customResponse) {
        var o = new DataWrapper(customResponse);
        o.dataObject; // old data
        // assume something changed on the server
        o.reload(function(err, done) {
             o.dataObject; // new data
        });
    });
    
  • 更新dataObject中的数据,保留与以前相同的对象:

    DataObject.prototype.reload = function(callback) {
        client.GET(this, function(err, customResponse) {
            // Assign all properties from the response to the existing obj
            // Could also use $.extend, _.extend, etc
            Object.assign(this, customResponse.dataObject);
            callback(this);
        }.bind(this));
    }
    
  • 只需传递回调中的新对象并忽略旧对象:

    DataObject.prototype.reload = function(callback) {
        client.GET(this, function(err, customResponse) {
            callback(customResponse.dataObject);
        });
    }