关于 JavaScript 错误处理的最完整指南(下半部),前端开发就业前景

因为使用了 Promise ,所以可以使用 then 来接收返回的内容,或者用 catch 来捕获出现的错误。

toUppercase(99)

.then(result => result)

.catch(error => console.error(error.message));

上面的执行结果:

Wrong type given, expected a string

除了 thencatch , Promise 中还有 finally 方法,这类似于try/catch 中的 finally

toUppercase(99)

.then(result => result)

.catch(error => console.error(error.message))

.finally(() => console.log(“Run baby, run”));

Promise, error, 和 throw


使用 Promise.reject 可以很方便的抛出错误:

Promise.reject(TypeError(“Wrong type given, expected a string”));

除了Promise.reject,我们也可以通过抛出异常来退出 Promise。

考虑以下示例:

Promise.resolve(“A string”).then(value => {

if (typeof value === “string”) {

throw TypeError(“Expected a number!”);

}

});

要停止异常传播,我们照常使用catch

Promise.resolve(“A string”)

.then(value => {

if (typeof value === “string”) {

throw TypeError(“Expected a number!”);

}

})

.catch(reason => console.log(reason.message));

这种模式在fetch中很常见:

fetch(“https://example-dev/api/”)

.then(response => {

if (!response.ok) {

throw Error(response.statusText);

}

return response.json();

})

.then(json => console.log(json));

这里可以使用catch拦截异常。如果我们失败了,或者决定不捕获它,异常可以在堆栈中自由冒泡。

使用 Promise 来处理定时器中的异常


使用定时器或事件无法捕获从回调引发的异常。

function failAfterOneSecond() {

setTimeout(() => {

throw Error(“Something went wrong!”);

}, 1000);

}

// DOES NOT WORK

try {

failAfterOneSecond();

} catch (error) {

console.error(error.message);

}

解决方案就是使用 Promise:

function failAfterOneSecond() {

return new Promise((_, reject) => {

setTimeout(() => {

reject(Error(“Something went wrong!”));

}, 1000);

});

}

使用reject,我们启动了一个 Promise 拒绝,它携带一个错误对象。

此时,我们可以使用catch处理异常:

failAfterOneSecond().catch(reason => console.error(reason.message));

使用 Promise.all 来处理错误


Promise.all(iterable) 方法返回一个 Promise 实例,此实例在 iterable 参数内所有的 promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);

const promise1 = Promise.resolve(“All good!”);

const promise2 = Promise.resolve(“All good here too!”);

Promise.all([promise1, promise2]).then((results) => console.log(results));

// [ ‘All good!’, ‘All good here too!’ ]

如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败的原因是第一个失败 promise 的结果。

const promise1 = Promise.resolve(“All good!”);

const promise2 = Promise.reject(Error(“No good, sorry!”));

const promise3 = Promise.reject(Error(“Bad day …”));

Promise.all([promise1, promise2, promise3])

.then(results => console.log(results))

.catch(error => console.error(error.message));

// No good, sorry!

同样,无论Promise.all的结果如何运行函数,finally 都会被执行:

Promise.all([promise1, promise2, promise3])

.then(results => console.log(results))

.catch(error => console.error(error.message))

.finally(() => console.log(“Always runs!”));

使用 Promise.any 来处理错误


Promise.any() (Firefox > 79, Chrome > 85) 接收一个 Promise 可迭代对象,只要其中的一个 promise 成功,就返回那个已经成功的 promise 。如果可迭代对象中没有一个 promise 成功(即所有的 promises 都失败/拒绝),就返回一个失败的 promiseAggregateError类型的实例,它是 Error 的一个子类,用于把单一的错误集合在一起。本质上,这个方法和Promise.all()是相反的。

const promise1 = Promise.reject(Error(“No good, sorry!”));

const promise2 = Promise.reject(Error(“Bad day …”));

Promise.any([promise1, promise2])

.then(result => console.log(result))

.catch(error => console.error(error))

.finally(() => console.log(“Always runs!”));

在这里,我们使用catch处理错误,输出如下:

AggregateError: No Promise in Promise.any was resolved

Always runs!

AggregateError对象具有与基本Error相同的属性,外加errors属性:

//

.catch(error => console.error(error.errors))

//

此属性是由reject产生的每个单独错误的数组

[Error: "No good, sorry!, Error: “Bad day …”]

使用 Promise.race 来处理错误


Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。

const promise1 = Promise.resolve(“The first!”);

const promise2 = Promise.resolve(“The second!”);

Promise.race([promise1, promise2]).then(result => console.log(result));

// The first!

这里说明,第一个 Promise 比第二个行执行完。那包含拒绝的情况又是怎么样的?

const promise1 = Promise.resolve(“The first!”);

const rejection = Promise.reject(Error(“Ouch!”));

const promise2 = Promise.resolve(“The second!”);

Promise.race([promise1, rejection, promise2]).then(result =>

console.log(result)

);

// The first!

如果把reject放在第一个又会怎么样?

const promise1 = Promise.resolve(“The first!”);

const rejection = Promise.reject(Error(“Ouch!”));

const promise2 = Promise.resolve(“The second!”);

Promise.race([rejection, promise1, promise2])

.then(result => console.log(result))

.catch(error => console.error(error.message));

// Ouch!

使用 Promise.allSettled 来处理错误


Promise.allSettled()方法返回一个在所有给定的promise都已经fulfilledrejected后的promise,并带有一个对象数组,每个对象表示对应的promise结果。

考虑下面示例:

const promise1 = Promise.resolve(“Good!”);

const promise2 = Promise.reject(Error(“No good, sorry!”));

Promise.allSettled([promise1, promise2])

.then(results => console.log(results))

.catch(error => console.error(error))

.finally(() => console.log(“Always runs!”));

我们传递给Promise.allSettled一个由两个Promise组成的数组:一个已解决,另一个被拒绝。

这种情况 catch 不会被执行, finally 永远会执行。

[

{ status: ‘fulfilled’, value: ‘Good!’ },

{

status: ‘rejected’,

reason: Error: No good, sorry!

}

]

使用 async/await 来处理错误


为了简单起见,我们使用前面的同步函数toUppercase,并通过在function关键字前放置async来将其转换为异步函数

async function toUppercase(string) {

if (typeof string !== “string”) {

throw TypeError(“Wrong type given, expected a string”);

}

return string.toUpperCase();

}

只要在函数前面加上async,该函数就会返回一个Promise。这意味着我们可以在函数调用之后进行thencatchfinally 操作

async function toUppercase(string) {

if (typeof string !== “string”) {

throw TypeError(“Wrong type given, expected a string”);

}

return string.toUpperCase();

}

toUppercase(“abc”)

.then(result => console.log(result))

.catch(error => console.error(error.message))

.finally(() => console.log(“Always runs!”));

当从 async 函数抛出异常时,我们就可以使用 catch 来捕获。

最重要的是,除了这种方式外,我们可以还使用try/catch/finally,就像我们使用同步函数所做的一样。

async function toUppercase(string) {

if (typeof string !== “string”) {

throw TypeError(“Wrong type given, expected a string”);

}

return string.toUpperCase();

}

async function consumer() {

try {

await toUppercase(98);

} catch (error) {

console.error(error.message);

} finally {

console.log(“Always runs!”);

}

}

consumer();

输出:

Wrong type given, expected a string

Always runs!

使用 async generators 来处理错误


JavaScript中的async generators是能够生成 Promises 而不是简单值的生成器函数。

async function* asyncGenerator() {

yield 33;

yield 99;

throw Error(“Something went wrong!”); // Promise.reject

}

基于 Promise,此处适用于错误处理的相同规则。 在异步生成器中 throw 将会触发 Promise 的reject,我们可以使用catch对其进行拦截。

为了使用异步生成器的 Promise,我们可以这样做:

  • then 方法

  • 异步遍历

从上面我们知道,在两次调用 yield之后,下一次会抛出一个异常:

const go = asyncGenerator();

go.next().then(value => console.log(value));

go.next().then(value => console.log(value));

go.next().catch(reason => console.error(reason.message));

输出结果:

{ value: 33, done: false }

{ value: 99, done: false }

Something went wrong!

别一种是使用 异步遍历for await...of:

async function* asyncGenerator() {

yield 33;

yield 99;

throw Error(“Something went wrong!”); // Promise.reject

}

async function consumer() {

for await (const value of asyncGenerator()) {

console.log(value);

}

}

consumer();

有了 async/await 我们可以使用 try/catch 来捕获异常:

async function* asyncGenerator() {

yield 33;

yield 99;

throw Error(“Something went wrong!”); // Promise.reject

}

async function consumer() {

try {

for await (const value of asyncGenerator()) {

console.log(value);

}

} catch (error) {

console.error(error.message);

}

}

consumer();

输出结果:

33

99

Something went wrong!

从异步生成器函数返回的迭代器对象也具有throw()方法,非常类似于其同步副本。在此处的迭代器对象上调用throw()不会引发异常,但是会被Promise拒绝

async function* asyncGenerator() {

yield 33;

yield 99;

yield 11;

}

const go = asyncGenerator();

go.next().then(value => console.log(value));

go.next().then(value => console.log(value));

go.throw(Error(“Let’s reject!”));

go.next().then(value => console.log(value)); // value is undefined

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

完整版面试题资料免费分享,只需你点赞支持,动动手指点击此处就可免费领取了

前端实习面试的套路


回顾项目

往往在面试时,面试官根据你简历中的项目由点及面地展开问答,所以请对你做过的最好的项目进行回顾和反思。回顾你做过的工作和项目中最复杂的部分,反思你是如何完成这个最复杂的部分的。

面试官会重点问你最复杂的部分的实现方法和如何优化。重点要思考如何优化,即使你项目中没有对那部分进行优化,你也应该预先思考有什么优化的方案。如果这部分答好了,会给面试官留下很不错的印象。

重点在于基础知识

这里指的基础知识包括:前端基础知识和学科基础知识。

前端基础知识:html/css/js 的核心知识,其中 js 的核心知识尤为重要。比如执行上下文、变量对象/活动对象(VO/AO)、作用域链、this 指向、原型链等。

学科基础知识:数据结构、计算机网络、算法等知识。你可能会想前端不需要算法,那你可能就错了,在大公司面试,面试官同样会看重学生这些学科基础知识。
你可能发现了我没有提到React/Vue这些框架的知识,这里得说一说,大公司不会过度的关注这方面框架的知识,他们往往更加考察学生的基础。
这里我的建议是,如果你至少使用或掌握其中一门框架,那是最好的,可以去刷刷相关框架的面试题,这样在面试过程中即使被问到了,也可以回答个 7788。如果你没有使用过框架,那也不需要太担心,把重点放在基础知识和学科基础知识之上,有其余精力的话可以去看看主流框架的核心思想。

img src=“https://i-blog.csdnimg.cn/blog_migrate/2d67d6978a7a195800fc2c8235fd80fa.jpeg” />

完整版面试题资料免费分享,只需你点赞支持,动动手指点击此处就可免费领取了

前端实习面试的套路


回顾项目

往往在面试时,面试官根据你简历中的项目由点及面地展开问答,所以请对你做过的最好的项目进行回顾和反思。回顾你做过的工作和项目中最复杂的部分,反思你是如何完成这个最复杂的部分的。

面试官会重点问你最复杂的部分的实现方法和如何优化。重点要思考如何优化,即使你项目中没有对那部分进行优化,你也应该预先思考有什么优化的方案。如果这部分答好了,会给面试官留下很不错的印象。

重点在于基础知识

这里指的基础知识包括:前端基础知识和学科基础知识。

前端基础知识:html/css/js 的核心知识,其中 js 的核心知识尤为重要。比如执行上下文、变量对象/活动对象(VO/AO)、作用域链、this 指向、原型链等。

学科基础知识:数据结构、计算机网络、算法等知识。你可能会想前端不需要算法,那你可能就错了,在大公司面试,面试官同样会看重学生这些学科基础知识。
你可能发现了我没有提到React/Vue这些框架的知识,这里得说一说,大公司不会过度的关注这方面框架的知识,他们往往更加考察学生的基础。
这里我的建议是,如果你至少使用或掌握其中一门框架,那是最好的,可以去刷刷相关框架的面试题,这样在面试过程中即使被问到了,也可以回答个 7788。如果你没有使用过框架,那也不需要太担心,把重点放在基础知识和学科基础知识之上,有其余精力的话可以去看看主流框架的核心思想。

  • 24
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值