如何防止 'UnhandledPromiseRejection' 用户输入错误?
How to prevent 'UnhandledPromiseRejection' on wrong user input?
我有 2 个文件,main.js 和 input.js。
在 input.js 中,我提示用户以“1-10”(字符串)格式给我一个间隔。后来我剪下这个字符串并从中得到 2 个数字并检查数字是否正确:
let getInput = () => {
return new Promise(function (resolve, reject) {
readline.question(`Give me interval (e.g.: 1-10).\n`, (input) => {
let fields = input.split('-');
let startNumber = Number(fields[0]);
let endNumber = Number(fields[1]);
if ((startNumber) && (endNumber) && (startNumber > 0) && (endNumber >= startNumber)) {
console.log(`ok`);
readline.close()
resolve([startNumber, endNumber]);
} else {
reject('not ok');
getInput();
}
});
});
}
在 main.js 中,我异步调用此函数并将其结果保存到变量中:
let intervalArray = await getInput();
.
.
.
someotherstuff
我的问题是如果我提供了错误的输入(例如“0-1”或“10-9”或“-10”)
我收到 UnhandledPromise 错误,因此代码不会执行更多。
我的目标是当用户输入错误时,'not ok, give me another' 应该出现在控制台中,程序应该等待另一个输入。如果该输入正确,则继续执行。如果不是,程序应该询问另一个输入。
我怎样才能做到这一点?
编辑:
这是完整的代码。
Input.js:
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
let getInput = () => {
return new Promise(function (resolve, reject) {
readline.question(`tol-ig formatumban (pl.: 1-10).\n`, (data) => {
let fields = data.split('-');
let startNumber = Number(fields[0]);
let endNumber = Number(fields[1]);
if ((startNumber) && (endNumber) && (startNumber > 0) && (endNumber >= startNumber)) {
console.log(`Kereses inditasa ${startNumber}-${endNumber} oldalakon.`);
readline.close()
resolve([startNumber, endNumber]);
} else {
readline.close();
reject(new Error('not ok'));
}
});
});
}
module.exports.getInput = getInput;
和main.js:
const puppeteer = require('puppeteer');
const { getInput } = require('./input');
const { mouseMovements } = require('./mouse');
const { tuneUserAgent } = require('./userAgent');
async function listItems() {
let intervalArray = null;
while (intervalArray === null) {
try {
let intervalArray = await getInput();
} catch (err) {
// write to user not ok
}
}
const browser = await puppeteer.launch({ headless: false });
const context = await browser.createIncognitoBrowserContext();
const page = await context.newPage();
const extractPartners = async url => {
const page = await context.newPage();
await tuneUserAgent(page);
await page.goto(url, { waitUntil: 'load' });
await page.waitFor(Math.round(Math.random() * 500) + 500);
await mouseMovements(page);
const partnersOnPage = await page.evaluate(() =>
Array.from(document.querySelectorAll("div.compact"))
.map(compact => (compact.querySelector(".logo a").href.slice(-16))));
await page.close();
const nextPageNumber = parseInt(url.match(/page=(\d+)$/)[1], 10) + 1;
if (nextPageNumber > endPage) {
console.log(`Terminate recursion on: ${url}`);
return partnersOnPage;
} else {
console.log(`Scraped: ${url}`);
const nextUrl = `https://marketingplatform.google.com/about/partners/find-a-partner?page=${nextPageNumber}`;
let randomWait = (Math.round(Math.random() * 2000) + 1000);
await page.waitFor(randomWait);
return partnersOnPage.concat(await extractPartners(nextUrl));
}
};
let startPage = intervalArray[0];
let endPage = intervalArray[1];
const firstUrl =
`https://marketingplatform.google.com/about/partners/find-a-partner?page=${startPage}`;
const partners = await extractPartners(firstUrl);
await browser.close();
return Promise.resolve(partners);
};
module.exports.listItems = listItems;
您必须处理错误。在使用 await 时,最简单的方法是使用 try catch。
try {
let intervalArray = await getInput();
} catch (err) {
// write to user not ok
}
您可以将其包装在循环中以不断请求用户输入新内容。
let intervalArray = null;
while (intervalArray === null) {
try {
let intervalArray = await getInput();
} catch (err) {
// write to user not ok
}
}
^^ 请记住从新 Promise 的 else
部分中删除 getInput();
。也许您还需要关闭阅读行,因为您将再次打开它。拒绝也类似于抛出错误,您应该始终将基于错误的对象发送到那里。
} else {
readline.close();
reject(new Error('not ok'));
}
编辑:在你更新后我创建了 POC。 readline.close()
实际上不应该存在(看起来只能使用一次),但这个 POC 看起来不错:
toBeRequired.js
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
let getInput = () => {
return new Promise(function (resolve, reject) {
readline.question(`tol-ig formatumban (pl.: 1-10).\n`, (data) => {
let fields = data.split('-');
let startNumber = Number(fields[0]);
let endNumber = Number(fields[1]);
if ((startNumber) && (endNumber) && (startNumber > 0) && (endNumber >= startNumber)) {
console.log(`Kereses inditasa ${startNumber}-${endNumber} oldalakon.`);
readline.close()
resolve([startNumber, endNumber]);
} else {
reject(new Error('not ok'));
}
});
});
}
module.exports.getInput = getInput;
server.js
const a = require('./toBeRequired');
async function x() {
let input = null;
while (input === null) {
try {
input = await a.getInput();
} catch (err) {
console.log('nooo');
}
}
}
x();
在同一文件夹中创建这两个文件 运行 node server.js
我有 2 个文件,main.js 和 input.js。 在 input.js 中,我提示用户以“1-10”(字符串)格式给我一个间隔。后来我剪下这个字符串并从中得到 2 个数字并检查数字是否正确:
let getInput = () => {
return new Promise(function (resolve, reject) {
readline.question(`Give me interval (e.g.: 1-10).\n`, (input) => {
let fields = input.split('-');
let startNumber = Number(fields[0]);
let endNumber = Number(fields[1]);
if ((startNumber) && (endNumber) && (startNumber > 0) && (endNumber >= startNumber)) {
console.log(`ok`);
readline.close()
resolve([startNumber, endNumber]);
} else {
reject('not ok');
getInput();
}
});
});
}
在 main.js 中,我异步调用此函数并将其结果保存到变量中:
let intervalArray = await getInput();
.
.
.
someotherstuff
我的问题是如果我提供了错误的输入(例如“0-1”或“10-9”或“-10”) 我收到 UnhandledPromise 错误,因此代码不会执行更多。 我的目标是当用户输入错误时,'not ok, give me another' 应该出现在控制台中,程序应该等待另一个输入。如果该输入正确,则继续执行。如果不是,程序应该询问另一个输入。
我怎样才能做到这一点?
编辑: 这是完整的代码。 Input.js:
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
let getInput = () => {
return new Promise(function (resolve, reject) {
readline.question(`tol-ig formatumban (pl.: 1-10).\n`, (data) => {
let fields = data.split('-');
let startNumber = Number(fields[0]);
let endNumber = Number(fields[1]);
if ((startNumber) && (endNumber) && (startNumber > 0) && (endNumber >= startNumber)) {
console.log(`Kereses inditasa ${startNumber}-${endNumber} oldalakon.`);
readline.close()
resolve([startNumber, endNumber]);
} else {
readline.close();
reject(new Error('not ok'));
}
});
});
}
module.exports.getInput = getInput;
和main.js:
const puppeteer = require('puppeteer');
const { getInput } = require('./input');
const { mouseMovements } = require('./mouse');
const { tuneUserAgent } = require('./userAgent');
async function listItems() {
let intervalArray = null;
while (intervalArray === null) {
try {
let intervalArray = await getInput();
} catch (err) {
// write to user not ok
}
}
const browser = await puppeteer.launch({ headless: false });
const context = await browser.createIncognitoBrowserContext();
const page = await context.newPage();
const extractPartners = async url => {
const page = await context.newPage();
await tuneUserAgent(page);
await page.goto(url, { waitUntil: 'load' });
await page.waitFor(Math.round(Math.random() * 500) + 500);
await mouseMovements(page);
const partnersOnPage = await page.evaluate(() =>
Array.from(document.querySelectorAll("div.compact"))
.map(compact => (compact.querySelector(".logo a").href.slice(-16))));
await page.close();
const nextPageNumber = parseInt(url.match(/page=(\d+)$/)[1], 10) + 1;
if (nextPageNumber > endPage) {
console.log(`Terminate recursion on: ${url}`);
return partnersOnPage;
} else {
console.log(`Scraped: ${url}`);
const nextUrl = `https://marketingplatform.google.com/about/partners/find-a-partner?page=${nextPageNumber}`;
let randomWait = (Math.round(Math.random() * 2000) + 1000);
await page.waitFor(randomWait);
return partnersOnPage.concat(await extractPartners(nextUrl));
}
};
let startPage = intervalArray[0];
let endPage = intervalArray[1];
const firstUrl =
`https://marketingplatform.google.com/about/partners/find-a-partner?page=${startPage}`;
const partners = await extractPartners(firstUrl);
await browser.close();
return Promise.resolve(partners);
};
module.exports.listItems = listItems;
您必须处理错误。在使用 await 时,最简单的方法是使用 try catch。
try {
let intervalArray = await getInput();
} catch (err) {
// write to user not ok
}
您可以将其包装在循环中以不断请求用户输入新内容。
let intervalArray = null;
while (intervalArray === null) {
try {
let intervalArray = await getInput();
} catch (err) {
// write to user not ok
}
}
^^ 请记住从新 Promise 的 else
部分中删除 getInput();
。也许您还需要关闭阅读行,因为您将再次打开它。拒绝也类似于抛出错误,您应该始终将基于错误的对象发送到那里。
} else {
readline.close();
reject(new Error('not ok'));
}
编辑:在你更新后我创建了 POC。 readline.close()
实际上不应该存在(看起来只能使用一次),但这个 POC 看起来不错:
toBeRequired.js
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
let getInput = () => {
return new Promise(function (resolve, reject) {
readline.question(`tol-ig formatumban (pl.: 1-10).\n`, (data) => {
let fields = data.split('-');
let startNumber = Number(fields[0]);
let endNumber = Number(fields[1]);
if ((startNumber) && (endNumber) && (startNumber > 0) && (endNumber >= startNumber)) {
console.log(`Kereses inditasa ${startNumber}-${endNumber} oldalakon.`);
readline.close()
resolve([startNumber, endNumber]);
} else {
reject(new Error('not ok'));
}
});
});
}
module.exports.getInput = getInput;
server.js
const a = require('./toBeRequired');
async function x() {
let input = null;
while (input === null) {
try {
input = await a.getInput();
} catch (err) {
console.log('nooo');
}
}
}
x();
在同一文件夹中创建这两个文件 运行 node server.js