更新'这'当返回用.apply()调用的函数时,从回调
Update 'this' from callback when returning function called with .apply()
我有一个ProjectClient
类,它包含一个用于进行HTTP调用的方法(.GET()
)。它以与节点请求相同的方式支持一些参数和回调,但也有一些复杂的url和头构建功能,这些功能也发生在幕后:
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函数回调为多个函数
- Meteor:异步函数回调异常:onAfterAction
- 从类方法中的 ajax post 函数回调函数更改 javascript 类属性
- jQuery动画函数回调错误
- jquery在html属性中添加函数回调,以便在其他事件中调用
- jquery getjson 函数:回调返回错误的字符串
- postMessage - 多个 postMessage 事件/函数/回调
- 在 Promise 调用的错误函数回调后附加对象的用法是什么
- 单击事件后的 JavaScript 函数回调
- 设置超时函数回调静态变量
- Jquery UI 模式匿名函数回调以打开对话框
- 函数回调、局部变量和 chrome.storage.sync.get
- Jquery Ajax 没有拾取选项参数中指定的函数回调
- 如何在 javascript 中进行函数回调
- 用函数回调封装JavaScript
- jQuery JavaScript嵌套异步函数回调
- Node.js-匿名函数回调
- 函数回调超出范围
- php代码的Javascript函数回调
- 如何使用函数回调在更改时提交表单