在延迟为 "pending" 时使用 Bacon.js 禁用提交按钮

Using Bacon.js to disable submit button while deferreds are "pending"

我有一个表单,其中有很多图像 urls - 后端保留 url 字符串,图像直接上传到 S3。我想在上传过程中使用 Bacon.js 流来处理 disabling/enabling 表单的提交按钮。

我尝试了各种方法(使用 Bacon.fromPromises 的流,使用 fromPromise-d 延迟流和原始延迟总线并尝试手动区分两者)但没有找到了一个解决方案,a) 按预期工作并且 b) 感觉我不是在与图书馆作斗争。

事情就是这样,但如前所述,提交按钮过早地重新启用。

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);
});

Fiddle

*更新

@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);
    });

Updated Fiddle

我知道使用总线是不受欢迎的,所以如果有人对我如何使用流实现相同的行为有建议,我非常希望看到它。

如果您知道要上传的 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);
});

我对您发布的代码感到有点担心的是这些流永远不会终止。您可能会考虑进行重构,以便通过单击创建持续搜索,并在所有流完成后终止。 (例如,merge 上传流并重新启用该合并的 onEnd 中的按钮。)

我会制作一个流,并在您发出请求时将其映射到 -1,在您收到响应时将其映射到 +1。然后,您可以 运行 对流进行折叠,并在它等于 0 时启用按钮。