我是在百度上搜广东网站建设,用wordpress建站要不要用宝塔,网站建设伍际网络,北京网站编程培训用专门的数据类型描述异常#xff0c;能便于串联可能出错的操作。Option类型就是这张容器#xff0c;在没有值时也能串联操作。
js中常用Promise来处理异步调用#xff0c;本文将手动实现Promise的部分功能#xff0c;来探索这个类型的处理逻辑。
1 处理错误
TS表示和处… 用专门的数据类型描述异常能便于串联可能出错的操作。Option类型就是这张容器在没有值时也能串联操作。
js中常用Promise来处理异步调用本文将手动实现Promise的部分功能来探索这个类型的处理逻辑。
1 处理错误
TS表示和处理错误的常用模式有
1返回null。
2抛出异常。
3返回异常。
4Option类型。
这些处理机制各有千秋可根据实际的业务场景来选择使用。
1.1 处理错误的常规模式
1.1.1 返回null
在遇到错误时直接返回null其他情况下返回正常的值。
function parseDate() {let num Math.random();if (num 0.5) { // 模拟遇到错误的场景return null;}return new Date();
}
在调用此类函数时需要先检查它的返回结果然后再使用。
let result parseDate();
if (result) {console.log(result);
} else {console.log(出错啦);
}
这种方式是处理错误最为轻量的方式但是无法返回出错原因且返回的null也不利于程序的编写每次操作都需要检查返回结果是否为null太繁琐不利于嵌套和串联操作。
1.1.2 抛出异常
当遇到错误时直接抛出异常。
function parseDate() {let num Math.random();if (num 0.5) { // 模拟遇到错误的场景throw new RangeError(随机数值小于0.5);}return new Date();
}
在调用此类函数时需要使用try/catch来捕获错误。
try {console.log(parseDate());
} catch (error) {console.error(error);
}
这种方式可以指出失败原因但是需要使用try/catch来捕获。这样在串联或嵌套操作时将会使代码结构变得复杂。而在实际开发中开发人员可能不会将代码放在try/catch中不会去检查异常。
1.1.3 返回异常
在遇到错误时直接return 异常。
function parseDate() {let num Math.random();if (num 0.5) { // 模拟遇到错误的场景return new RangeError(随机数值小于0.5);}return new Date();
}
在调用此类函数时需要根据返回值类型做不同的处理。
let result parseDate();
if (result instanceof Error) {console.error(出错了 result.message);
} else {console.log(result);
}
这种方式比较轻量又能提供错误信息能强制使用方处理每一个异常。但是在串联和嵌套操作时会比较繁琐。
1.2 Option类型
Option不是JS内置的数据类型需要我们自己编写。它表示不返回一个值而是返回一个容器。该容器可能有一个值也可能没有。这个容器有一些方法让没有值时也能串联操作。
class CustomOptionT {constructor(private val: T) {}thenU(fun: (val:T) CustomOptionU) {return fun(this.val);}getValue(errorMessage: string) {return this.val || errorMessage;}
}function askInput() {let num Math.random();if (num 0.5) {return new CustomOption(null)}return new CustomOption(2023-12-16 12:34:24);
}function parseDate(str: string | null) {if (str) {return new CustomOption(new Date(str));} else {return new CustomOption(null);}
}let result askInput().then(parseDate).getValue(转化失败);
console.log(result);上面代码有两个问题1实际上当第一个函数报错的时候就意味着整个调用链都出错了因此在后面的调用上应该及时知晓上个返回值是个空值以免执行不必要的操作。2在调用getValue这个参数时当前一个函数返回正常值时是不需要往getValue传递参数的。
下面是优化后的代码
interface CustomOptionT {thenU(fun: (val:T) CustomOptionU): CustomOptionU;getValue(val:T):T;
}class CustomSomeT implements CustomOptionT {constructor(private value: T) {}getValue(): T {return this.value;}thenU(fun: (val:T) CustomOptionU): CustomOptionU {return fun(this.value);}
}class CustomNone implements CustomOptionnever {getValueT(val: T): T {return val;}thenU(): CustomOptionU {return this;}
}function askInput() {let num Math.random();if (num 0.5) {return new CustomNone()}return new CustomSome(2023-12-16 12:34:24);
}function parseDate(str: string | null) {if (str) {return new CustomSome(new Date(str));} else {return new CustomNone();}
}let result askInput().then(parseDate).getValue(转化失败);
console.log(result);
2 处理回调
JS异步程序的核心基础是回调。回调其实就是常规函数只是作为参数传给另一个函数。就像在同步程序一样另一个函数在操作完成后调用会调函数。
但在串联和嵌套操作中容易导致“回调金字塔”。
function askInput(callback: (val: string) void) {let num Math.random();if (num 0.5) {throw new RangeError(随机数小于0.5);} else {callback(2023-12-13 12:00);}
}function parseDate(str: string,callback: (date: Date) void) {callback(new Date(str));
}askInput((val: string) { // 嵌套第一层if (val) {parseDate(val,(date:Date) { // 嵌套第二层console.log(date);})}
});
2.1 Promise
在JS中常用Promise来解决“回调金字塔”问题。
1实现Promise的then方法来处理回调。
type Executor (resolve: ExecutorResolve,reject: ExecutorReject
) voidtype CustomPromiseStatus pending | finished | rejected;
type ExecutorResolve (val: any)void;
type ExecutorReject (error: any) void;class CustomPromise {private status: CustomPromiseStatus;private value: any;private error: null;private resolveCallbackList: ArrayExecutorResolve;private rejectCallbackList: ArrayExecutorReject;constructor(executor: Executor) {this.status pending;this.value null;this.error null;this.resolveCallbackList [];this.rejectCallbackList [];const resolve:ExecutorResolve (val: any) {this.status finished;this.value val;try {this.resolveCallbackList.forEach(callback callback(this.value));} catch (e) {reject(e);}};const reject:ExecutorReject (error: any) {this.status rejected;this.error error;this.rejectCallbackList.forEach(callback callback(error));}executor(resolve,reject);}then(resolve:ExecutorResolve,reject: ExecutorReject) {switch (this.status) {case finished:try {resolve(this.value);} catch (e) {reject(e);}break;case rejected:reject(this.error);break;default:this.resolveCallbackList.push(resolve);this.rejectCallbackList.push(reject);}}
}function askInputPromise() {return new CustomPromise((resolve, reject) {let num Math.random();if (num 0.5) {reject(new RangeError(随机数小于0.5));} else {resolve(2023-12-16 12:34:24);}})
}let promise askInputPromise();
promise.then((val:string) {console.log(new Date(val));
},(error) {console.log(出错啦 error);
})2then 方法返回Promise类型实现可串联使用。
type Executor (resolve: ExecutorResolve,reject: ExecutorReject
) voidtype CustomPromiseStatus pending | finished | rejected;
type ExecutorResolve (val: any) any;
type ExecutorReject (error: any) void;let IsPromise (val: any) : val is CustomPromise {return val instanceof CustomPromise;
};class CustomPromise {private status: CustomPromiseStatus;private value: any;private error: null;private resolveCallbackList: ArrayExecutorResolve;private rejectCallbackList: ArrayExecutorReject;constructor(executor: Executor) {this.status pending;this.value null;this.error null;this.resolveCallbackList [];this.rejectCallbackList [];const resolve:ExecutorResolve (val: any) {this.status finished;this.value val;try {this.resolveCallbackList.forEach(callback callback(this.value));} catch (e) {reject(e);}};const reject:ExecutorReject (error: any) {this.status rejected;this.error error;this.rejectCallbackList.forEach(callback callback(error));}executor(resolve,reject);}then(resolve:ExecutorResolve,reject?: ExecutorReject) {return new CustomPromise((resolveNew, rejectNew) {const resolveFun:ExecutorResolve (val: any) {try {let res resolve(this.value);if (IsPromise(res)) {res.then(resolveNew);} else {resolveNew(res);}} catch (e) {rejectNew(e);}};const rejectFun: ExecutorReject (error: any) {if (reject) {reject(error);}if (rejectNew) {rejectNew(error);}}switch (this.status) {case finished:try {resolveFun(this.value);} catch (e) {rejectFun(e);}break;case rejected:rejectFun(this.error);break;default:this.resolveCallbackList.push(resolveFun);this.rejectCallbackList.push(rejectFun);}})}
}function askInputPromise() {return new CustomPromise((resolve, reject) {let num Math.random();if (num 0.5) {reject(new RangeError(随机数小于0.5));} else {resolve(2023-12-16 12:34:24);}})
}askInputPromise().then((val:string) {return new CustomPromise((resolve, reject) {console.log(输入参数 val);resolve(new Date(val));})
}).then((val:any) {console.log(最终结果,val)
},(error: any) {console.log(在这里就出错了,error);
});