中断或取消 Promise 链

Promise 已经成为了 JavaScript 管理异步操作的重要工具之一. 然而, 有的时候还是会很头痛:

Promise
    // 等价于 `Promise.resolve(undefined).then`.
    .then(() => {
        // 开始.
    })
    .then(() => {
        if (wantToBreakHere) {
            // 怎样在这里终止这个 Promise 链?
        }
    })
    .then(() => {
        // 一定条件下不想被执行的代码.
    });

当然我们可以嵌套后面的 then, 但如果整条链很长很厚, 也必然很痛苦.

不过很多 Promise 实现都有一个 catch 方法, 我们可以做一点点小动作:

/** 用于中断的信号 */
class BreakSignal { }

Promise
    .then(() =>http://www.0771ybyy.com/news/1799.html<> {
        // 开始.
    })
    .then(() => {
        if (wantToBreakHere) {
            // 抛出中断信号.
            throw new BreakSignal();
        }
    })
    .then(() =>http://www.0771ybyy.com/news/1801.html<> {
        // 需要跳过的部分.
    })
    // 接住中断信号.
    .catch(BreakSignal, () => { });

其实个人觉得这么干还是比较优雅的, 但如果中间还有其他的 onrejected handler, 则需要手动传递 BreakSignal (再次抛出).

现在考虑另一种不同于 break 的情形:

page.on('load', () => {
    Promise
        .then(() => asyncMethodA())
        .then(result >http://www.0771ybyy.com/news/1800.html<=> asyncMethodB(result))
        .then(result => {
            // 更新一些东西...
        });
});

如果 load 事件在短时间内触发了两次, 我们则需要取消前一个 Promise 链, 或者至少要防止它执行完成后做一些不该做的事情 (比如更新数据或者 UI).

那我们可以考虑这么处理:

class BreakSignal { }

let context;

/** 创建包含上下文信息的 wrapper */
function createWrapper() {
    let currentContext =>http://www.0771ybyy.com/news/1803.html< context;

    return function (handler) {
        return function () {
            if (context !== currentContext) {
                throw new BreakSignal();
            }

            return>http://www.0771ybyy.com/news/1802.html< handler.apply(undefined, arguments);
        };
    };
}

page.on('unload', () => {
    context = undefined;
});

page.on('load', (>http://www.0771ybyy.com/news/1805.html<) => {
    context = {};
    let wrap = createWrapper();

    Promise
        //>http://www.0771ybyy.com/news/1804.html< 包起来~
        .then(wrap(asyncMethodA))
        .then(wrap(asyncMethodB))
        .then(result => {
            // 更新一些东西...
        })
        .catch(BreakSignal, () => { });
});

[AD] ThenFail

因为平时用的是自己的 Promise 实现 - ThenFail - 所以自己有需求一定要满足自己. 我愉快地添加了伪 break 语句.

import { Promise }>http://www.0771ybyy.com/news/1807.html< from 'thenfail';

Promise
    .then(() => {
        // 开始.
    })
    .then(() => {
        if (wantToBreakHere) {
            //>http://www.0771ybyy.com/news/1806.html< 就是这么任性.
            Promise.break;
        }

        return Promise
            .then(() => {
                Promise.break;
            })
            .then(() => {
                // 这里永远也不会执行.
            });
            // 嵌套的情况不需要最下面的 `enclose()`.
    })
    .then(() => {
        // 需要跳过的部分.
    })
    // 结束当前的 Promise >http://www.0771ybyy.com/news/1809.html<链的上下文 (context), 避免 `break` 掉太多.
    // 如果这个 Promise 链会被返回, 交给不在你控制范围内的代码, 那么 enclose 操作非常重要~
    .enclose();

其实还能 break ThenFail 的 each helper:

Promise
    .each([1, 2, 3], value => {
        if (value > 1) {
            Promise.break;

            // 或者异步地 >http://www.0771ybyy.com/news/1808.html<`break`:
            return Promise
                .then(() => {
                    // 做一些事情.
                })
                .break;
        }
    })
    .then(completed => {
        if (completed) {
            // 一些代码...
        }
    });

当然有的同学可能看出来了, Promise.break 这个伪语句实际上是一个会抛出异常的 getter, 抛出的异常则是类似于BreakSignal 的这么个东西 (虽然实现上一个是 object1 === object2, 一个是 object instanceof Class).

前面有提到 ThenFail 中上下文的概念, 如果需要取消相同上下文的整个 Promise 链, 只需要释放对应的 context 即可.

let context;

page.on('unload', () => {
    context.dispose();
});

page.on('load', () => {
    let promise = Promise
        .then(() => asyncMethodA())
        .then(result => asyncMethodB(result))
        .then(result => {
            // 更新一些东西...
        });

    context = promise.context;
});

另外, 释放上下文也会释放嵌套的上下文.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在JavaScript中,Promise是用于管理异步操作的重要工具之一。然而,有时我们可能需要中断一个Promise的执行。有几种方法可以实现这个目标。 一种方法是使用自定义的异常来抛出中断信号。你可以定义一个BreakSignal类作为中断的信号,然后在想要中断的地方使用throw关键字抛出BreakSignal异常。然后,在Promise的后续部分使用catch方法来捕获BreakSignal异常并执行相应的处理逻辑。这样,当中断信号被抛出时,Promise的执行将会被中断。 另一种方法是使用第三方库或自己实现的Promise库,其中包含了类似于Promise.break的特殊语法来中断Promise的执行。在这种情况下,你可以使用类似于Promise.break的语法来直接中断Promise的执行。具体的实现方法可能因使用的库而有所不同,但基本思路是使用类似于break的语法来中断Promise的执行。 无论你选择哪种方法,中断Promise的关键是在适当的地方抛出一个信号或使用特殊的语法来终止Promise的执行。然后,你可以根据需要在后续部分进行相应的处理。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [中断promise](https://blog.csdn.net/qq_24147051/article/details/108049705)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值