async / await引发错误“ UnhandledPromiseRejectionWarning:TypeError:无法读取未定义的属性'xyz'”,但并不总是

问题描述 投票:0回答:3

我有一个简单的代码,提示用户输入,然后对输入进行某些操作。在代码的trial run中,我得到error: UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'node' of undefined,但并非总是如此。我不明白为什么它有时仅会引发错误?


input-interface.js

'use strict';

const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

module.exports = {
  prompt: function prompt(question) {
    return new Promise((resolve) => {
      rl.setPrompt(question);
      rl.prompt();
      rl.once("line", resolve);
    });
  }
}

interactive-request-procedures.js

'use strict'

const input_interface = require('./input_interface');
const InteractiveRequestProcedures = Object.create(input_interface);

InteractiveRequestProcedures.createInputNode = async function createInputNode() {
  return {
    position: await this.prompt("Position? start(s), end(e), position(integer) > "),
    value: await this.prompt("Value? > "),
  };  
}

InteractiveRequestProcedures.inputRemoveKey = async function inputRemoveKey() {
  return await this.prompt("Remove Key? > ");
}

InteractiveRequestProcedures.requestProcedure = async function requestProcedure() {
  const procedure = await this.prompt("Procedure? insert(i), delete(d) > ");

  if (procedure === "i") {
    return {
      procedure,
      node: await this.createInputNode(),
    }   
  } else if (procedure === "d") {
    return {
      procedure,
      node: await this.inputRemoveKey(),
    }   
  } else {
    console.log(`Invalid input '${procedure}': Please select again\n`);
    await this.requestProcedure();
  }
}

module.exports = InteractiveRequestProcedures;

main-program.js

UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'node' of undefined所在的行在下面的代码中用注释突出显示。

'use strict';

const LinkedList = Object.create(require('./interactive-request-procedures'));

LinkedList.setup = function setup() {
  this.lhead = -1;

  this.last = -1;


  this.free = -1;

  this.key = [];
  this.next = [];
  this.prev = [];

  this.listLength = 0;

  this.input();
}

LinkedList.input = async function input() {
  while(true) {
    let input = await this.requestProcedure(); //UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'node' of undefined
    let { position, value } = input.node;

    if (input.procedure === "i") {
      switch (position) {
        case '1':
        case 's':
          this.prepend(value); // implementation details not shown
          break;
        case 'e':
        case `${this.next.length}`:
          this.append(value); // implementation details not shown
          break;
        default:
          /* Check to see if position is an integer */
          if ( (position ^ 0) === parseInt(position, 10) ) {
            console.log(`Invalid input: Position ${position} is not an integer`);
            continue;
          }

          /* Check to see if position exceeds list length */
          if (position > this.listLength) {
            console.log(`Invalid input: Position ${position} exceeds list length ${this.listLength}\nTry Again\n`);
            continue;
          }

          this.insertAt(value, position); // implementation details not shown
      }
    }

    if (input.procedure === 'd') this.deleteNode(input.node);

    const resp = await this.prompt("Continue? y / n > ");
    if (resp === "n")
      break;
    console.log("\n");
  }
  console.log(this.list);
}

LinkedList.setup();

试运行

我用node main-program.js执行代码

me@myBook ~/main-program (master) $ node skip-list.js 
Procedure? insert(i), delete(d) > aef
Invalid input 'aef': Please select again

Procedure? insert(i), delete(d) > i
Position? start(s), end(e), position(integer) > 2332
Value? > 23
(node:41451) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'node' of undefined
    at Object.input (main-program.js:51:34)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:189:7)
(node:41451) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (reject
ion id: 1)
(node:41451) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

me@myBook ~/main-program (master) $ node skip-list.js 
Procedure? insert(i), delete(d) > i
Position? start(s), end(e), position(integer) > 3232
Value? > 2
Invalid input: Position 3232 is not an integer
Procedure? insert(i), delete(d) > i
Position? start(s), end(e), position(integer) > 234
Value? > 34
Invalid input: Position 234 is not an integer
Procedure? insert(i), delete(d) > 244355
Invalid input '244355': Please select again

Procedure? insert(i), delete(d) > i
Position? start(s), end(e), position(integer) > 3232
Value? > 224
(node:41455) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'node' of undefined
    at Object.input (main-program.js:51:34)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:189:7)
(node:41455) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (reject
ion id: 1)
(node:41455) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Value? > 434
javascript async-await
3个回答
1
投票

尽管您应该始终在异步/等待代码周围使用try ... catch块,但这将无助于解决“为什么有时会工作有时会失败的问题?”

您的问题在这段代码中:

} else {
    console.log(`Invalid input '${procedure}': Please select again\n`);
    await this.requestProcedure();
}

输入无效的输入后,此代码块将不提供该函数的返回值。

重现您的问题:

  • 启动程序
  • 输入无效的输入
  • 应用程序显示:无效的输入'$ {procedure}':请再次选择
  • 输入有效输入
  • 抛出异常(无法读取属性“节点”)

要解决此问题,只需在最后一个其他地方返回:

} else {
    console.log(`Invalid input '${procedure}': Please select again\n`);
    return await this.requestProcedure();
}

1
投票

我们需要处理错误,以防止发生此类异常

[当我们使用异步等待时,我们需要使用'try catch'块当使用诺言时,我们需要使用'then and catch'块

try {
 // positive case
} catch(error) {
 // handle errors here
}

1
投票

此行中的异步操作:

let input = await this.requestProcedure();

失败,因此未设置input变量。因此,当它继续执行下一行时:

let { position, value } = input.node;

您得到Cannot read property 'node' of undefined,因为输入不包含值。您应该在try catch中执行异步命令,以便可以看到错误的详细信息:

try {
    let input = await this.requestProcedure();
    // run the rest of your code
}
catch(error) {
    // Do something with the error (e.g. log it, print it)
}

很遗憾,我们无法确定是什么原因导致了异步操作问题,但这是您在问题中提到的错误的原因。这也将帮助您调试它。

© www.soinside.com 2019 - 2024. All rights reserved.