- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我的同事喜欢的 Java 8 编码风格是一直链接异步调用,例如
CompletionStage<E> someMethod() {
return doSomething().thenCompose(a -> {
// ...
return b;
}).thenCompose(b -> {
// ...
return c;
}).thenCompose(c -> {
// ...
return d;
}).thenApply(d -> {
// ...
return e;
});
}
我有类似上面的内容,但还有一个额外的挑战:我需要在后面的 lambda 中记忆在一些 lambda 中检索到的值。例如,
CompletionStage<E> someMethod() {
return doSomething().thenCompose(a -> {
// ...
Foo foo = fooDAO.getFoos(a);
// ...
return b;
}).thenCompose(b -> {
// ...
return c;
}).thenCompose(c -> {
// ...
Bar bar = barDAO.getBars(foo);
// ...
return d;
}).thenApply(d -> {
// ...
return someResult(d, bar);
});
}
当我在外部范围内声明 Foo foo;
和 Bar bar;
时,我收到关于它们不是最终的或实际上不是最终的错误。我读到了有关使用包装器使它们有效地最终化的信息,但是这样做对我来说似乎很老套(我不明白为什么允许这样做...)
我读到 Java 8 没有添加对元组的支持(虽然它考虑了 BiVal
,也许我可以用来传递给 BiFunction
lambda)。所以我尝试使用配对,例如
return doSomething().thenCompose(a -> {
// ...
Foo foo = fooDAO.getFoos(a);
// ...
return new Pair<>(foo, b);
}).thenCompose(fooAndB -> {
然后在任何我需要调用foo
的地方,
Foo foo = fooAndB.getKey();
但这感觉在语义上是错误的。而且,它不起作用!我不知道为什么,因为我认为 lambda 参数的范围与其外部范围相同,因此所有 lambda 参数都可以从稍后链接的 lambda 中访问。
lambda 参数的真正范围是什么,是否有一种惯用的或至少在语义上无害的方式来做我想做的事情,同时保持链接?
基于打破链条的答案很好,因为它们可能对 future 的观众有用,但就我而言,偏离此 repo 协议(protocol)中的主导风格可能会导致 PR 对话和批准延迟,所以我喜欢保留链接的解决方案。或者,解释或演示试图保持链接是多么疯狂。谢谢!
最佳答案
由于您提到了同事喜欢的编码风格,您可能已经知道使用嵌套调用的替代方法:
CompletionStage<E> someMethod() {
return doSomething().thenCompose(a -> {
// ...
Foo foo = fooDAO.getFoos(a);
// ...
CompletableFuture<B> resultB = ...;
return resultB.thenCompose(b -> {
// ...
CompletableFuture<C> resultC = ...;
return resultC;
}).thenCompose(c -> {
// ...
Bar bar = barDAO.getBars(foo);
// ...
CompletableFuture<D> resultD = ...;
return resultD.thenApply(d -> {
// ...
return someResult(d, bar);
});
});
});
}
这会立即解决您的问题,但代价是代码的可读性稍差一些。但是这个问题可以通过从您的代码中提取一些方法来轻松解决:
CompletionStage<E> someMethod() {
return doSomething()
.thenCompose(this::processA);
}
private CompletionStage<E> processA(final A a) {
// ...
Foo foo = fooDAO.getFoos(a);
// ...
final CompletableFuture<B> result = ...;
return result
.thenCompose(this::processB)
.thenCompose(c -> processCAndFoo(c, foo));
}
private CompletionStage<C> processB(B b) {
// ...
return ...;
}
private CompletionStage<E> processCAndFoo(final C c, final Foo foo) {
// ...
Bar bar = barDAO.getBars(foo);
// ...
final CompletableFuture<D> result = ...;
return result
.thenApply(d -> someResult(d, bar));
}
通过这样做,您可以避免嵌套的 lambda(并尊重您同事的首选代码风格),但您也可以获得可读性和可测试性,因为您现在有几个更容易理解和单元测试的小方法。
关于java - 在 Java 8 中使用先前链接的 thenCompose lambda 的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52669585/
我的应用将 SceneKit 内容的“页面”与图像和文本交替。当我从图像页面前进到新的 SceneKit 页面时,前一个 SceneKit 页面中的内容会短暂显示,然后被新内容替换。时髦。 我只使用一
我正在尝试处理(在 C# 中)包含一些数字数据的大型数据文件。给定一个整数数组,如何对其进行拆分/分组,以便如果下一个 n(两个或更多)是负数,则前一个 n 元素被分组。例如,在下面的数组中,应该使用
刚接触promises,研究过。所以我的代码和我的理解: sql.connect(config).then(function(connection) { return connection.req
目前我在 if (roobaf) block 中有一些代码,这取决于 foo 和 bar 是否为假。我可以在 block 内再次检查这些条件,但感觉像是不必要的代码重复。 if (foo) {
我是一名优秀的程序员,十分优秀!