我有一个 ProjectClient
类,其中包含一个用于进行 HTTP 调用的方法 (.GET()
)。它以与 node-request 相同的方式支持一些参数和回调。 ,但在幕后也有一些复杂的 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
类添加一个名为 reload()
的便捷方法,它会回调 client.GET()
方法并重新加载自身,但我希望能够使用从服务器返回的新版本的 DataObject
更新 this
:
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
的原始副本也没有被更新——就好像它被克隆或复制了,而不是指向原始副本的指针?
这是一个证明失败的测试。如何确保传递指向 dataObject
的正确指针?
var now = Date.now()
client.GET('test', function(err, getResponse) {
var dataObject = new DataObject(getResponse.dataObject)
getResponse.dataObject.reloadTest = now // 1452109996140
console.log('now', now, 'getResponse.dataObject.reloadTest', getResponse.dataObject.reloadTest)
// now 1452109996140 getResponse.dataObject.reloadTest 1452109996140
client.PUT(getResponse.dataObject, function(err, putResponse) {
// updated 1452109996140 1452109996140
console.log('putResponse.dataObject.reloadTest', putResponse.dataObject.reloadTest)
// putResponse.dataObject.reloadTest 1452109996140
dataObject.reload(function(err, response) {
// updated 1452109996140 1452109996140
console.log('done', dataObject.reloadTest, 'response.dataObject.reloadTest', response.dataObject.reloadTest)
// done 1452109916111 response.dataobject.reloadTest 1452109996140
})
})
})
最佳答案
简短的回答是,你不能。您实际上无法将该对象换成另一个对象。一些选项:
使用包装器对象,并为其提供
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); }); }
关于javascript - 返回使用 .apply() 调用的函数时从回调中更新 'this',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34641028/