我尝试编写一个函数,它返回一些API(AgileCRMManager)的promise版本。 api的设计与请求非常相似。
但我在功能切换方面遇到了一些问题。函数无法访问自己的原型。我得到了以下日志输出:
[Function: getContactByEmail]
[Function: getContactByEmail]
TypeError: this.getOptions is not a function
at getContactByEmail (/Users/Tilman/Documents/Programme/NodeJS/async_test/node_modules/agile_crm/agilecrm.js:116:24)
at /Users/Tilman/Documents/Programme/NodeJS/async_test/routes/portal.js:30:5
at restPromise (/Users/Tilman/Documents/Programme/NodeJS/async_test/routes/portal.js:29:10)
at Object.<anonymous> (/Users/Tilman/Documents/Programme/NodeJS/async_test/routes/portal.js:22:1)
at Module._compile (module.js:541:32)
at Object.Module._extensions..js (module.js:550:10)
at Module.load (module.js:456:32)
at tryModuleLoad (module.js:415:12)
at Function.Module._load (module.js:407:3)
at Function.Module.runMain (module.js:575:10)
这是来自agile_crm的getOptions的部分:
ContactAPI.prototype.getOptions = function getOptions() {
this._options = {
host: this.domain,
headers: {
'Authorization': 'Basic ' + new Buffer(this.email + ':' + this.key).toString('base64'),
'Accept': 'application/json'
}
};
return this._options;
};
这是我的代码(如果我用a.contactAPI.getContactByEmail更改restFunction,它可以工作。但是我想让它用于更多功能):
var AgileCRMManager = require("agile_crm")
var a = new AgileCRMManager("user-domain",
"api-key",
"user-mail")
restPromise('ds@umzuege-selisch.de',a.contactAPI.getContactByEmail)
.then(console.log)
.catch(console.error)
function restPromise(data, restFunction) {
console.log(restFunction); // => [Function: getContactByEmail]
console.log(a.contactAPI.getContactByEmail); // => [Function: getContactByEmail]
return new Promise(function(fulfill, reject){
//a.contactAPI.getContactByEmail(
restFunction(
data,
function(data){
fulfill(data)
},
function(error){
reject(new Error(error))
}
)
})
}
任何想法如何交出功能和api仍然可以工作?
答案 0 :(得分:1)
你误解了this
在javascript中的运作方式。通常情况下,我会投票支持这样的问题,但这似乎是一个需要进一步解释的特定用例。有关this
如何运作的完整说明,我建议您阅读此问题的答案:How does the "this" keyword in Javascript act within an object literal?。
现在,问题是在js中this
的值取决于你如何调用函数。如果函数是方法,this
将解析为该方法所属的对象:
a.foo = function () { console.log(this) };
a.foo() // should output `a`
但是如果函数是一个不属于对象的简单函数,那么this
可以是全局对象(浏览器中的窗口),也可以是未定义的,具体取决于严格模式。请注意,js解释天气或不是函数是调用函数时的方法。不是在定义函数时。这有一个有趣的后果:
a.foo = function () { console.log(this) };
b = a.foo;
b(); // here b is a simple function because it's not something.b
// so the output is either the global object or undefined
这是在这行代码中发生的事情:
restPromise('ds@umzuege-selisch.de',a.contactAPI.getContactByEmail)
您将a.contactAPI.getContactByEmail
作为函数参考传递。因此它失去了它是a.contactAPI
的一部分而变成一个简单函数的事实。通过如何调用函数可以清楚地看到这一事实:
restFunction( //...
请注意,您正在调用restFunction
,这是a.contactAPI.getContactByEmail
的函数引用。由于它被简单地称为restFunction()
而不是a.contactAPI.restFunction()
,因此函数中的this
指向全局对象(或取决于严格模式而未定义),而不是a.contactAPI
。
有几种方法可以解决这个问题。
在匿名函数中包装a.contactAPI.getContactByEmail
,以便您可以使用正确的this
调用它:
restPromise(
'ds@umzuege-selisch.de',
function(data,ok,err){
a.contactAPI.getContactByEmail(data,ok,err);
}
)
使用.bind()
:
restPromise(
'ds@umzuege-selisch.de',
a.contactAPI.getContactByEmail.bind(a.contactAPI)
)
修改restPromise()
以接受对象而不是函数。