独家配方 - Promise 使用小技巧

简介: 虽然现在前端开发中大部分的异步代码中的回调都在慢慢的被 Promise 所取代,然而大部分的原生 API 和一些库都还只有回调的调用方式。于是很多时候我们需要将一些库、原生 API 转换成 Promise,此时不可避免的就是写一个 Promise 将其包裹

网络异常,图片无法展示
|

虽然现在前端开发中大部分的异步代码中的回调都在慢慢的被 Promise 所取代,然而大部分的原生 API 和一些库都还只有回调的调用方式。于是很多时候我们需要将一些库、原生 API 转换成 Promise,此时不可避免的就是写一个 Promise 将其包裹:

const readFile = file => {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.readAsString(file);
        reader.addEventListener('load', e => {
            resolve(e.result);
        });
        reader.addEventListener('error', e => {
            reject(e);
        });
    });
};
复制代码

然而,在 n 年前的一天,我突然看这段代码不顺眼,好不容易拜托了回调地狱,又来了一层 Promise,我表示很难受,于是我将它改成了这样:

const readFile = file => {
    let resolve, reject;
    const promise = new Promise((_resolve, _reject) => {
        resolve = _resolve;
        reject = _reject;
    });
    const reader = new FileReader();
    reader.readAsString(file);
    reader.addEventListener('load', e => {
        resolve(e.result);
    });
    reader.addEventListener('error', e => {
        reject(e);
    });
    return promise;
};
复制代码

乍看之下,为了节省一个层级缩进,增加了 n 行代码,不过别着急,这里还有优化的空间:

const controllerFactory = () => {
    let resolve, reject;
    const promise = new Promise((_resolve, _reject) => {
        resolve = _resolve;
        reject = _reject;
    });
    return [promise, resolve, reject];
};
const readFile = file => {
    const [controller, success, error] = controllerFactory();
    const reader = new FileReader();
    reader.readAsString(file);
    reader.addEventListener('load', e => {
        success(e.result);
    });
    reader.addEventListener('error', e => {
        error(e);
    });
    return controller;
};
复制代码

这样将 Promise 的实例化部分的代码抽离出来,我们就得到一个比较干净的 readFile 了,看起来舒服多了 😌。

这样的写法好处就是,当你有个超大的方法需要转换为 Promise 写时,不用再跑到方法头尾加上 Promise 包裹,直接在将实参里的 successerror 去掉,添加 factory 代码并返回即可:

源代码:

const myFunc = (success, error) => {
    // ...
    // a lot of code
    if (e) {
        error(e);
    } else {
        success(result);
    }
};
复制代码

Promise 改造后:

const myFunc = () => {
    return new Promise((resolve, reject) => {
        // ...
        // a lot of code
        if (e) {
            reject(e);
        } else {
            resolve(result);
        }
    });
};
复制代码

或是需要判断包裹区域进行包裹:

const myFunc = () => {
    // ...
    // a lot of code
    return new Promise((resolve, reject) => {
        if (e) {
            reject(e);
        } else {
            resolve(result);
        }
    });
};
复制代码

而使用 controllerFactory 改造后:

const myFunc = () => {
    const [controller, success, error] = controllerFactory();
    // ...
    // a lot of code
    if (e) {
        error(e);
    } else {
        success(result);
    }
    return controller;
};
复制代码

个人感觉这样代码看起来更舒适,当然,这种写法是好是坏见仁见智,欢迎指点讨论。

相关文章
|
前端开发
promise的一些巨坑
promise的一些巨坑
|
12月前
|
前端开发
20 # 实现 promise 的 all 方法
20 # 实现 promise 的 all 方法
44 0
|
12月前
|
前端开发
7 # promise 的 then 方法
7 # promise 的 then 方法
75 0
|
5月前
|
前端开发 JavaScript API
Promise 对象与 Promises/A+ 规范
Promise 对象与 Promises/A+ 规范
71 0
|
5月前
|
消息中间件 前端开发 JavaScript
Promise:使用Promise,告别回调函数
Promise:使用Promise,告别回调函数
60 1
Promise:使用Promise,告别回调函数
|
前端开发 程序员
promise的链式调用和promise的嵌套的实现
promise的链式调用和promise的嵌套的实现
177 0
|
前端开发 JavaScript 开发者
Promise从手写到扩展 | Promise/Generator/async | [Promise系列二](一)
Promise从手写到扩展 | Promise/Generator/async | [Promise系列二](一)
109 0
|
前端开发 JavaScript 开发者
Promise从手写到扩展 | Promise/Generator/async | [Promise系列二](二)
Promise从手写到扩展 | Promise/Generator/async | [Promise系列二](二)
142 0
|
监控 前端开发
ES6躬行记(23)——Promise的静态方法和应用
  Promise有四个静态方法,分别是resolve()、reject()、all()和race(),本节将着重分析这几个方法的功能和特点。
|
存储 前端开发 算法
Promise源码解密-Promise A+标准
Promise源码解密-Promise A+标准