Web 前端 - 优雅地 Callback 转 Promise :aw
前言
当今 ES7 标准大行其道,使用 async + await 将异步逻辑同步书写已经普及,但是却有许多旧库或旧代码尚未完全 Promise 化,急需一个小工具去挖去这代码中藓疾。
设计和实现
由于通常情况下,回调函数 callback 都是作为最后一个参数传入主调函数,所以 aw 小工具的设计如下:
// Transform Callback-style function to Promise-style function. export type AwCallback<RES> = (res?: RES) => void; export function aw(num: number): Promise<void>; export function aw<A, B, C, D, E, /**/ RES>(exec: (a: A, b: B, c: C, d: D, e: E, callback: AwCallback<RES>) => void, a: A, b: B, c: C, d: D, e: E): Promise<RES>; export function aw<A, B, C, D, /*---*/ RES>(exec: (a: A, b: B, c: C, d: D, /*-*/ callback: AwCallback<RES>) => void, a: A, b: B, c: C, d: D /*-*/): Promise<RES>; export function aw<A, B, C, /*------*/ RES>(exec: (a: A, b: B, c: C, /*-------*/ callback: AwCallback<RES>) => void, a: A, b: B, c: C /*-------*/): Promise<RES>; export function aw<A, B, /*---------*/ RES>(exec: (a: A, b: B, /*-------------*/ callback: AwCallback<RES>) => void, a: A, b: B /*-------------*/): Promise<RES>; export function aw<A, /*------------*/ RES>(exec: (a: A, /*-------------------*/ callback: AwCallback<RES>) => void, a: A /*-------------------*/): Promise<RES>; export function aw</*---------------*/ RES>(exec: (/*-------------------------*/ callback: AwCallback<RES>) => void /*-------------------------*/): Promise<RES>; export async function aw(execOrNum: number | ((...res: any[]) => void), ...args: any[]) { const exec = typeof execOrNum !== "number" ? execOrNum : (r: any) => setTimeout(r, execOrNum); const res = await new Promise(r => exec.apply(null, [...args, r])); if (res instanceof Error) throw res; /*---------------*/ else return res; }
使用
const func = (arg,callback)=>callback(arg); const sum = (arg0:number,arg1:number,arg2:number,callback:(res:number)=>void )=>setTimeout(()=>callback(arg0+arg1+arg2),1000); // 用法1:睡眠 1 秒 await aw(1000) // 用法2:await aw(主调函数,依次顺序列出所有参数不包括回调函数) const result1 = await aw(func,arg); const result0 = await aw(sum, arg0,arg1,arg2) ;