NodeJS:函数式编程 - 无法访问切换函数中的原型 [英] NodeJS: Functional Programming - No access to prototype in handover function

查看:42
本文介绍了NodeJS:函数式编程 - 无法访问切换函数中的原型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试编写一个函数,该函数返回某些 API (AgileCRMManager) 的承诺版本.api 的设计与请求非常相似.

I try to write a function, that returns a promise version for some API (AgileCRMManager). The design of the api works pretty similar to request.

但是我在功能移交方面遇到了一些问题.函数无法访问自己的原型.我得到以下日志输出:

But i have some Problems with the handover of the Function. The Function have no access to the prototype of its own. I got following log output:

[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 的部分:

This is the part with getOptions from agile_crm:

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,它可以工作.但我想拥有更多功能):

This is my Code (if i change restFunction with a.contactAPI.getContactByEmail, it works. But i want to have it for more functions):

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 仍然可以工作吗?

Any Idea how i can hand Over the function and api will still work?

推荐答案

您误解了 this 在 javascript 中的工作方式.通常我会投票结束这样的问题,但这似乎是一个需要进一步解释的特定用例.有关 this 如何工作的完整说明,我建议阅读以下问题的答案:this"是怎么来的?Javascript 中的关键字在对象字面量中起作用吗?.

You've misunderstood how this works in javascript. Normally I'd vote to close questions like this but this seems to be a specific use case that requires further explanation. For a full explanation of how this works I'd suggest reading the answer from this question: How does the "this" keyword in Javascript act within an object literal?.

现在,问题是在js中this的值取决于你如何调用一个函数.如果函数是方法,this 解析为该方法所属的对象:

Now, the problem is that in js the value of this depends on how you call a function. If a function is a method, this resolves to the object the method belongs to:

a.foo = function () { console.log(this) };
a.foo() // should output `a`

但是如果函数是一个不属于对象的简单函数,那么 this 要么是全局对象(浏览器中的窗口),要么是 undefined,具体取决于严格模式.请注意,当您调用函数时,js 会解释天气与否,函数是一种方法.不是在定义函数时.这会产生有趣的后果:

But if the function is a simple function that is not part of an object then this is either the global object (window in browsers) or undefined depending on strict mode. Note that js interprets weather or not a function is a method when you call the function. Not when you define the function. This has interesting consequences:

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

漏洞

这行代码是这样的:

The Bug

This is what happens in this line of code:

restPromise('ds@umzuege-selisch.de',a.contactAPI.getContactByEmail)

您将 a.contactAPI.getContactByEmail 作为函数引用传递.因此它失去了它是 a.contactAPI 的一部分的事实,而是变成了一个简单的函数.这个事实可以从你如何调用函数中清楚地看出:

You're passing a.contactAPI.getContactByEmail as a function reference. Therefore it loses the fact that it's part of a.contactAPI and instead becomes a simple function. This fact can be clearly seen by how you call the function:

restFunction( //...

请注意,您正在调用 restFunction,它是对 a.contactAPI.getContactByEmail 的函数引用.由于它被简单地称为 restFunction() 而不是 a.contactAPI.restFunction(),因此函数中的 this 指向全局对象(或 undefined 取决于严格模式)而不是 a.contactAPI.

Note that you're calling restFunction which is a function reference to a.contactAPI.getContactByEmail. Since it is called simply as restFunction() instead of a.contactAPI.restFunction() the this in the function points to the global object (or undefined depending on strict mode) instead of a.contactAPI.

有几种方法可以解决这个问题.

There are several ways you can fix this.

  1. a.contactAPI.getContactByEmail 包裹在匿名函数中,以便您可以使用正确的 this 调用它:

  1. Wrap a.contactAPI.getContactByEmail in an anonymous function so you can call it with the proper 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() 以接受一个对象而不是一个函数.

  • Modify restPromise() to accept an object instead of a function.

    这篇关于NodeJS:函数式编程 - 无法访问切换函数中的原型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆