[英]Strange behavior of Rx.Observable.prototype.fromEvent()
Today I've seen a strange problem when using RxJS. 今天,我在使用RxJS时遇到了一个奇怪的问题。 Please help me inspect it.
请帮我检查一下。
The problem I am working on is: "Given an array of image URLs, load and append all images to a div." 我正在研究的问题是:“给出图像URL数组,加载所有图像并将其附加到div。”
All the code snippets to demonstrate is here: 所有要演示的代码段在这里:
https://pastebin.com/F3ZkH3F8 https://pastebin.com/F3ZkH3F8
At the beginning, I used the first snippet
. 在开始时,我使用
the first snippet
。
However, Rx.Observable.prototype.flatMap
sometimes puts the images in wrong order (this behavior is noticed in the documentation). 但是,
Rx.Observable.prototype.flatMap
有时会以错误的顺序放置图像(此行为在文档中已注意到)。 So, I changed to use concatMap
( second snippet
). 因此,我更改为使用
concatMap
( second snippet
)。
This time, only the first image is loaded. 这次仅加载第一张图像。 I took some time inspect the problem.
我花了一些时间检查问题。 I doubt that event
load
is not trigged from image
. 我怀疑事件
load
不会从image
触发。 But the most confusing situation is that when I add some code to listen to image
's load
event only, it showed me that the event is trigged properly... ( third snippet
). 但是最令人困惑的情况是,当我添加一些代码以仅监听
image
的load
事件时,它表明该事件已正确触发...( third snippet
)。
Then I decided to write another version using $.Deferred
( fourth snippet
). 然后,我决定使用
$.Deferred
( fourth snippet
)编写另一个版本。
It worked... 有效...
Could you please tell me what is the problem? 你能告诉我是什么问题吗? Thank you very much!
非常感谢你!
Because fromEvent(image, 'load')
on the first sub-observable is not completed, other sub-observables are waiting forever. 由于第一个子可观察
fromEvent(image, 'load')
未完成,因此其他子可观察对象将永远等待。 So you should complete sub-observable after first event. 因此,您应该在第一个事件之后完成可观察的子项目。
Use take(1)
. 使用
take(1)
。
excerpt from your second snippet 第二段摘录
...
var loadedImageStream = Rx.Observable
.fromEvent(image, 'load')
.map(function() {
return image;
})
...
Add take(1) to complete sub-observable 添加take(1)以完成子可观察
...
var loadedImageStream = Rx.Observable
.fromEvent(image, 'load')
.map(function() {
return image;
})
.take(1)
...
EDIT: 编辑:
Using concatMap
makes loading image sequential, so it is slow. 使用
concatMap
可使图像顺序加载,因此速度很慢。
If you pass index
, you can use replace
instead of append
to keep the order. 如果传递
index
,则可以使用replace
而不是append
来保持顺序。 In this case, you can use flatMap
, which enables fast concurrent loading. 在这种情况下,可以使用
flatMap
,它可以实现快速并发加载。
$(function () {
var imageURLList = [
'https://placehold.it/500x100',
'https://placehold.it/500x200',
'https://placehold.it/500x300',
'https://placehold.it/500x400',
'https://placehold.it/500x500'
];
var imagesDOM = $('#images');
Rx.Observable
.fromArray(imageURLList)
.do(function (imageURL) {
imagesDOM.append(new Image()); // placeholder
})
.flatMap(function (imageURL, index) {
var image = new Image();
var loadedImageStream = Rx.Observable
.fromEvent(image, 'load')
.map(function () {
return [image, index];
})
.take(1)
image.src = imageURL;
return loadedImageStream;
})
.subscribe(function (image_index) {
var image = image_index[0];
var index = image_index[1];
imagesDOM.children().get(index).replaceWith(image);
})
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.