使用Bacon.js在"pending"状态下禁用提交按钮

9
我有一个表单,其中包含许多图片URL - 后端将URL字符串持久化,并且图片直接上传到S3。我想使用Bacon.js流来处理在上传过程中禁用/启用表单提交按钮。
我尝试了各种方法(使用Bacon.fromPromises的流流,使用fromPromise-d延迟的流和原始延迟的总线,并尝试手动区分两者),但没有找到既能够正常工作又不需要费力地与库对抗的解决方案。
目前情况如上所述,但是请注意,提交按钮会过早地重新启用。
function toResultStream(promise) {
  return Bacon.fromPromise(promise)
}

var deferreds = $('a').asEventStream('click', function (event) {
    event.preventDefault();
    var deferred = $.Deferred();

    // simulate upload
    setTimeout(function () {
        deferred.resolve(true);
    }, _.random(200, 1600))

    setTimeout(function () {
        deferred.rejectWith(false);
    }, _.random(200, 1600))

    return deferred;        
});

deferreds.onValue(function () {
    $('#submit').attr('disabled', true);
})

// only takes completed deferreds into consideration
var ongoingSearch = deferreds.flatMap(function (d) {
    return toResultStream(d);
})
.mapError(true)
.onValue(function () {
    $('#submit').attr('disabled', false);
});

JSFiddle链接

*更新

@mjs2600的答案足以引导我找到解决方案。

以下是我最终采取的方法:

var bus = new Bacon.Bus();

var deferreds = $('a').asEventStream('click', function (event) {
    // ...
    bus.push(-1);        
    // ...
});

var ongoingSearch = deferreds
    .flatMap(toResultStream)
    .mapError(1)
    .merge(bus)
    .scan(0, function (memo, n) { return memo + n; })
    .onValue(function (value) {
        var disabled = value < 0;
        $('#submit').attr('disabled', disabled);
    });

更新后的 JSFiddle 示例

我知道使用总线不被推荐,如果有人能提供使用流来实现同样行为的建议,我将非常感激。

2个回答

5

如果你知道要上传的url数量,你可以添加skip来忽略除最后一个url之外的所有响应。

var numStreams = 1;
var ongoingSearch = deferreds.flatMap(function (d) {
    return toResultStream(d);
}) 
.mapError(true)
.skip(numSteams-1)
.onValue(function () {
    alert('fooo');
    $('#submit').attr('disabled', false);
});

我对您发布的代码有一个小小的担忧,即这些流永远不会终止。您可以考虑重构代码,使得 ongoingSearch 是由单击创建的,并在所有流都完成后终止。(例如,将上传流合并并在合并的 onEnd 内重新启用按钮。)


谢谢您的回复,但请注意请求的数量是动态的。我一定会记住您关于流终止的建议。虽然这个页面存在时间很短,但这并不是粗心的借口。 - pdoherty926

1
我会创建一个流并将其映射为 -1 当您发出请求时,将其映射为 +1 当您收到响应时。然后,您可以在流上运行 fold 并在它等于 0 时启用按钮。

1
谢谢您。您建议使用-1、1和fold/scan正是我需要的推动力。 - pdoherty926

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接