【问题标题】:Can I untangle this nesting of 'when' promise invocations?我可以解开这种“何时”承诺调用的嵌套吗?
【发布时间】:2025-12-22 02:00:12
【问题描述】:

我是 when.js javascript 库的新手,但我熟悉 C# 中的异步编程。这就是为什么我觉得这段代码很笨拙:

filters.doFilter('filter1name', reqAndPosts).then(function(filter1) {
    filters.doFilter('filter2name', filter1).then(function(filter2) {
        filters.doFilter('filter3name', filter2).then(function (posts) {
            renderView(posts); 
        });
    });
    return filter1;
});

我基本上希望按顺序调用三个方法,每个方法的输出通过管道传送到下一个方法。无论如何我可以将这段代码重构为更“类似序列” - 即摆脱嵌套?我觉得这里的when-framework 缺少一些东西。我做的不对吧?

【问题讨论】:

标签: javascript asynchronous promise when-js


【解决方案1】:

既然doFilter返回了一个promise,我们可以做

filters.doFilter('filter1name', reqAndPosts)
    .then(function(filter1) {
        return filters.doFilter('filter2name', filter1);
    })
    .then(function(filter2) {
        return filters.doFilter('filter3name', filter2);
    })
    .then(renderView);

【讨论】:

  • Nilzor,虽然您目前的方法将使先前操作的结果在所有后续操作(范围)中可用,但 @thefourtheye 方法可以使代码更清晰、更易于阅读。两者都有不同的适用场景。
  • 是的。更简洁的代码是我现在正在寻找的,所以就是这样。谢谢。
  • @AkashAgrawal 不,正如我的回答所示,有更好的方法:)
  • @FlorianMargaine 太好了!谢谢。 :)
【解决方案2】:

还有另一个选项可以同时具有更清晰的缩进和以前的结果的优点:使用withThis

filters.doFilter('filter1name', reqAndPosts).withThis({}).then(function(filter1) {
    this.filter1 = filter1; // since we used withThis, you use `this` to store values
    return filters.doFilter('filter2name', filter1);
}).then(function(filter2) {
    // use "this.filter1" if you want
    return filters.doFilter('filter3name', filter2);
}).then(renderView);

【讨论】:

  • When.js 现在也绑定了
【解决方案3】:

稍加思考,您就可以编写一个通用的实用函数,它将一个起始对象和一个过滤器序列作为其参数,动态构建所需的.then 链,并返回多重过滤结果的承诺。

函数将如下所示...

function doFilters(filterArray, startObj) {
    return filterArray.reduce(function(promise, f) {
        return promise.then(function(result) {
            return filters.doFilter(f, result);
        });
    }, when(startObj));
}

...这是对“The Collection Kerfuffle”一节中给出的here 模式的改编。

你想要的操作,调用如下:

doFilters(['filter1name', 'filter2name', 'filter3name'], reqAndPosts).then(function(result) {
    //All filtering is complete.
    //Do awesome stuff with the result.
});

如果它没有被销毁并且在范围内,doFilters() 将仍然可以在您的代码中的其他地方使用:

doFilters(['f1', 'f2', 'f3'], myOtherObject).then(function(result) {
    //...
});

只需稍加努力,您就可以通过将doFilters() 作为filters 的一种方法来整理事情。这将是最好的。

【讨论】:

  • 不错。这或多或少是when.pipeline() 所做的,对吧?我开始掌握 Javascript 中的承诺,您的帖子在这方面肯定有所帮助。 github.com/cujojs/when/blob/master/docs/api.md#whenpipeline
  • Nilzor,我并不是一个真正的when 人——我的大部分 Promise 经验都在 jQuery 中——但据我了解,when 提供了三种相关方法when.reducewhen/sequence、和when/pipeline 是“处理异步承诺和任务数组的好方法”。如果不浏览文档',我不确定哪个最相关,但可能是when/pipeline。我使用了 JS 的原生 array.reduce(),它正在迅速成为首选方法。 .reduce 的 polyfill 或类似 when 的库。
最近更新 更多