【问题标题】:Nodejs async function prototype chain errorNodejs异步函数原型链错误
【发布时间】:2018-04-24 18:20:28
【问题描述】:

为什么这段代码可以编译

var Person =  function() {
console.log("CALLED PERSON")};

Person.prototype.saySomething = function() {
console.log("saySomething PERSON")};

var ape = new Person();
ape.saySomething();

此代码抛出错误无法设置未定义的属性“saySomething”

var Person =  async function() {
console.log("CALLED PERSON")};

Person.prototype.saySomething = function() {
console.log("saySomething PERSON")};

var ape = new Person();
ape.saySomething();

【问题讨论】:

  • 因为(async function () {}).constructor.name !== (function () {}).constructor.name
  • 永远不要创建构造函数async。它将返回一个承诺,而不是一个新对象。
  • 感谢回复,为什么不能将'AsyncFunction'添加到对象原型,而可以添加'Function' ((function () {}).constructor.name)。

标签: node.js asynchronous async-await prototype


【解决方案1】:

当您使用 async function() {} 时,您正在声明一个 asynchronous function 对象。这与普通的 function 对象不同。异步函数对象没有原型。

所以,当你尝试这样做时:

var Person =  async function() {
  console.log("CALLED PERSON")
};

Person.prototype.saySomething = function() {
  console.log("saySomething PERSON")
};

Person.prototypeundefined,因为在 asynchronous function 对象上没有 prototype。因此,尝试将某些内容分配给 Person.prototype.saySomething 会导致您看到错误,因为 Person.prototypeundefined

这有一些逻辑,因为异步函数不能用作构造函数,因为异步函数总是返回一个承诺,所以它永远不能像let obj = new f()那样返回一个新对象。因此,拥有 .prototype 属性没有任何意义,因为它不能以这种方式使用。

如果你真的想异步创建一个对象,你总是可以创建一个 async 工厂函数,它返回一个用对象解析的承诺。

【讨论】:

  • “一个异步函数总是返回一个承诺”解释每一件事。 stackoverflow.com/questions/43422932/…
  • 这个怎么样? var Person = function() { console.log("CALLED PERSON") }; Person.prototype.saySomething = async function() { console.log("saySomething PERSON") };
【解决方案2】:

可以在原型链的末尾添加异步函数。

请注意,这在 nodejs 8.11.1+ 中运行良好。

// lets start with defining some cool async function who takes the time and 
// awaits a promise 

async function someCoolAsyncFunction() {
    // this let will be returned after timeout in a different value.
    let coolStuff = 'still boring';

    // do something cool which takes time 
    await new Promise((resolve, reject) => setTimeout(() => {
        coolStuff = 'an epiphany';
        resolve();
    }, 1000))
    return coolStuff;
}

// Now let's define the 'regular' prototype chain with it's boring functions.

function Person(p) { 
     this.constructorPropery = p;
     return this;
}

Person.prototype.notAsync = function() {
     // do something regular in the prototype chain
     console.log("Let's build some ",this.constructorPropery)
     this.kindOfPerson = 'Regular and boring'; 
     return this;   
}

// And now, lets add an async function to this chain

Person.prototype.someAsyncFunction = async function() {
    // you will still have access to 'this' in this function as long as the
    // previous function in the prototype chain returnes 'this'
    console.log('I used to be someone ',this.kindOfPerson);

    // Now, this is our time to shine, lets await something cool
    this.lifeChangingEvent = await someCoolAsyncFunction();
    console.log('Until I had ',this.lifeChangingEvent);
    a.kindOfPerson = 'enlightened';
    console.log('and now I am ', a.kindOfPerson);
    return this;
}

所以这会起作用:

new Person('charachter').notAsync().someAsyncFunction();

但这不会工作:

new Person('charachter').someAsyncFunction().notAsync();

如果你真的需要原型链之外的'this'中的数据,你也可以这样做:

let myself = new Person('charachter').notAsync();
console.log('myself.kindOfPerson is: ',myself.kindOfPerson);
myself.someAsyncFunction(); 
console.log('myself.kindOfPerson now is: ',myself.kindOfPerson);

请务必记住哪个原型是哪个函数的异步函数,或者为此使用您自己的命名对流。

【讨论】:

  • 这行得通吗? await new Person('charachter').someAsyncFunction();
猜你喜欢
  • 1970-01-01
  • 2021-10-20
  • 2021-07-14
  • 1970-01-01
  • 2018-09-05
  • 1970-01-01
  • 2016-12-03
  • 2017-02-26
  • 1970-01-01
相关资源
最近更新 更多