小程序中如何优雅的捕捉异步方法的异常

原生小程序中如何优雅的捕捉异步方法的异常?下面本篇文章给大家介绍一下小程序中优雅的使用async await异步编程的方法,希望对大家有所帮助!

最近开始写一个开源的云开发社区小程序,在写的过程中慢慢的摸索了一些对于开发和测试的过程中又帮助的奇技淫巧。这篇文章讲一下在 原生小程序中如何优雅的捕捉异步方法的异常

传统方法

在ES7之后,我们往往使用 async await 语法来进行异步编程,如果我们要捕捉异常的话一般有以下两种方式

try catch

async func(){
     //do something
}
try {
    const res = await func()
} catch (error) {
    //handle error
}

首先是 try catch 捕捉异常,使用 try catch 确实可以很方便的去处理异常,也可以阻止后面方法的进行,但是在开发的过程中咱们常常不止一个异步方法,大量使用 try catch 不仅写的不爽,也绝对算不上优雅。

Promise.catch()

async func(){
     //do something
}

const res = await func().catch(error=>{
    //handle error
})

Promise对象内部了try catch ,我们可以使用链式调用的方法来处理异常。相比try catchPromise.catch() 写起来当然是爽很多的,看着也比较优雅了。

但是当我们想要在捕捉到错误后停止方法的继续执行,那么 Promise.catch() 就没办法做到了,如下例子

async func(){
     //do something
}

const res = await func().catch(error=>{
    // 即使return也无效
    return
})
// 如果有错误的话我就不执行了

优雅方式

await-to-js github链接

https://github.com/scopsy/await-to-js

await-to-js 这个库应该很多人了解过了,它是一个异步请求的包装器,可以用于处理异步请求的错误,根据我们上面的需求改造为使用 await-to-js 的例子如下

import to from 'await-to-js';

async func(){
     //do something
}

const [err,res] = await to(func())
if(err){
    //handle error
    return
}
// 如果有错误的话我就不执行了

通过将我们的异步方法作为 to() 方法的参数,返回值通过一个数组解构获取,数组第一个值为捕捉到的错误,第二个值为正常执行的返回值。

await-to-js的实现原理也非常简单,就是使用 Promise.catch()获取到异常后再将结果返回在一个数组中, 源代码如下

export function to<T, U = Error> (
	promise: Promise<T>,
	errorExt?: object
  ): Promise<[U, undefined] | [null, T]> {
	return promise
	  .then<[null, T]>((data: T) => [null, data])
	  .catch<[U, undefined]>((err: U) => {
		if (errorExt) {
		  const parsedError = Object.assign({}, err, errorExt);
		  return [parsedError, undefined];
		}
  
		return [err, undefined];
	  });
  }
  
  export default to;

小程序中使用

在小程序中,我们使用npm包并不方便,因此我们可以直接将源码拿出来单独使用,再加以改造的话就可以优雅的进行异步编程啦,我自己的改造方式如下。

// lib/awaitTo.js
module.exports = function to(promise, description=unknown) {
	const pages = getCurrentPages()
	const route = pages[pages.length - 1].route||'unknown'
	description = `[${route}]---[${description}]`
	console.time(description)
	return promise
		.then(function (data) {
			console.timeEnd(description)
			return [null, data];
		})
		.catch(function (err) {
			wx.showToast({
				title: '请求失败',
				icon: none
			})
			return [err, undefined];
		});
}

我通过 getCurrentPages() 的方式获取到异步方法执行时对应的页面路由,在将第二个参数改为自己对异步方法的一个描述,每一次调用异步方法的时候就会在 控制台输出执行时间。 实际使用的例子如下:

const to = require(../../lib/awaitTo)
const [err, res] = await to(db.collection(post).add({
        data: form
}),addPost)
if (err) {
        // 处理我的错误
        return
}
// 成功后执行的逻辑

控制台打印的执行时间输出如下,打印格式是

【路由页面】---【方法描述】:执行时间

1.png

当然我的封装方式是针对我自己的代码,你也可以根据你的实际业务再进行改造,例如埋点的统一入口之类的,可以极大提升开发效率!

总结

在使用云开发时,为了开发体验不得不使用原生的语言去写,相对闭塞的环境就使得很多web端的方法没法使用,在近期的摸索中我也找到了很多提升原生小程序开发体验的方式,之后将会陆续更新。

【相关学习推荐:小程序开发教程

相关文章

概述 消息能力是小程序能力中的重要组成,我们为开发者提供了...
判断H5页面环境在微信中还是小程序中 用小程序提供的wx.mini...
wx.reLaunch和wx.navigateTo,wx.navigateTo的区别 2019-03-...
微信小程序如何从数组里取值_微信小程序 传值取值的几种方法...
H5项目接入微信授权登录,通过 UA 区分微信还是普通浏览器:...
微信小程序获取data-xx=&quot;&quot;属性的值,自定...