木偶:在异步函数中使用await调用的javascript函数中引发自定义错误消息

时间:2018-09-15 16:29:07

标签: javascript node.js error-handling async-await puppeteer

我正在使用puppeteer构建一个小型应用程序以自动在线填写表格。我以Gmail为例,无需单击“提交”按钮即可测试功能。

我打开Gmail URL,并使用名为findInputFieldByName的功能找到用户名输入字段。代码工作正常,网页打开,并且我可以在用户名字段中看到伪造者打印test@gmail.com

代码是:

const puppeteer = require('puppeteer');

const gmailUrl='https://accounts.google.com/signin/v2/identifier?continue=https%3A%2F%2Fmail.google.com%2Fmail%2F&service=mail&sacu=1&rip=1&flowName=GlifWebSignIn&flowEntry=ServiceLogin';
const userName='test@gmail.com';
const findInputFieldByName = (page,inputName) => {
    return page.$('input[name="'+inputName+'"]');
}

(async () => {
    try {
    const Browser = await puppeteer.launch({headless:false,
                                        defaultViewport:{width:600,height:800}
                                        });
    const page=await Browser.newPage();

    page.on('load', () => console.log('Page loaded ' + page.url()));
    await page.goto(gmailUrl);

    const userNameElement = await findInputFieldByName(page,'identifier').catch(error => {
       console.log('The following error occurred: ' + error);
       });
    await userNameElement.type(userName,{delay:50});
    } catch(e) {console.log('main program error:' + e);
    }

})();

如您所见,代码正在返回的HTML中寻找名称为identifier的输入字段。但是,如果我要使用Gmail登录页面上没有的其他名称(例如 identifier1 ),我希望代码抛出一条自定义错误消息,内容为“ 输入字段”找不到名称标识符1 ”,并且代码应停止。

如果我更改

const userNameElement = await findInputFieldByName(page,'identifier').catch(error => {
           console.log('The following error occurred: ' + error);
           });

const userNameElement = await findInputFieldByName(page,'identifier1').catch(error => {
           console.log('The following error occurred: ' + error);
           });

我收到以下错误:

  

主程序错误:TypeError:无法读取null的属性“ type”

我知道这是因为功能findInputFieldByName并未失败。由于没有名称为 identifier1 的输入字段,因此它仅返回一个空对象。尝试输入电子邮件地址时,代码实际上失败了。

但是,我的问题是如何在findInputFieldByName函数中引发错误,以使其在const userNameElement = await findInputFieldByName..执行时停止?

我尝试在findInputFiledByName函数中使用诺言:

const findInputFieldByName = (page,inputName) => {
    let promise=new Promise(function (resolve,reject){
    var elm= page.$('input[name="'+inputName+'"]');
    if (elm.length>0) {
        resolve(elm);
    } else {
        reject(Error('Could not find input name ' + inputName));
    }
});
}

但是我收到以下消息:

  

主程序错误:TypeError:无法读取未定义的属性“ catch”   (节点:12332)UnhandledPromiseRejectionWarning:错误:找不到输入名称标识符1

     

在C:\ Users \ test1.js:11:10

     

在新的Promise中(<匿名>)

     

在findInputFieldByName(C:\ Users \ test1.js:6:14)

     

在C:\ Users \ test1.js:26:32

     

在<匿名>

     

在process._tickCallback(内部/进程/next_tick.js:188:7)(节点:12332)UnhandledPromiseRejectionWarning:未处理的承诺   拒绝。该错误是由抛出异步内部引起的   没有捕获块或拒绝承诺   未使用.catch()处理。 (拒绝ID:1)(节点:12332)[DEP0018]   DeprecationWarning:已弃用未处理的承诺拒绝。在   未来,未处理的承诺拒绝将终止   具有非零退出代码的Node.js进程。

我应该如何处理自定义错误?我是Java新手,不胜感激。enter code here

1 个答案:

答案 0 :(得分:0)

首先,返回promise,而不是将其分配给变量。

const findInputFieldByName = (page, inputName) => {
  return new Promise(((resolve, reject) => { // <-- Return it

之后,如果需要,您可以throw出错。

await findInputFieldByName(page,'identifier').catch(error => {
    throw ('The following error occurred: ' + error) // <-- pass the error to main program
});