今天,我在使用RxJS时遇到了一个奇怪的问题。请帮我检查一下。

我正在研究的问题是:“给出图像URL数组,加载所有图像并将其附加到div。”

所有要演示的代码段在这里:

https://pastebin.com/F3ZkH3F8

一开始,我使用the first snippet

但是,Rx.Observable.prototype.flatMap有时会以错误的顺序放置图像(此行为在文档中已注意到)。因此,我更改为使用concatMapsecond snippet)。

这次仅加载第一张图像。我花了一些时间检查问题。我怀疑事件load是否不会从image触发。但是最令人困惑的情况是,当我添加一些代码以仅监听imageload事件时,它表明该事件已正确触发...(third snippet)。

然后,我决定使用$.Deferredfourth snippet)编写另一个版本。

有效...

你能告诉我是什么问题吗?非常感谢你!

最佳答案

由于第一个子可观察对象的fromEvent(image, 'load')尚未完成,因此其他子可观察对象将永远等待。因此,您应该在第一个事件之后完成可观察的子项目。

使用take(1)

第二段摘录

...
var loadedImageStream = Rx.Observable
                            .fromEvent(image, 'load')
                            .map(function() {
                                return image;
                             })
...


添加take(1)以完成子可观察

...
var loadedImageStream = Rx.Observable
                            .fromEvent(image, 'load')
                            .map(function() {
                                return image;
                             })
                            .take(1)
...


编辑:

使用concatMap可使图像顺序加载,因此速度较慢。

如果通过index,则可以使用replace代替append保持顺序。在这种情况下,可以使用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);
        })
})

关于javascript - Rx.Observable.prototype.fromEvent()的奇怪行为,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44171653/

10-11 13:43