在延迟"待定"时使用Bacon.js禁用提交按钮

pdo*_*926 9 javascript jquery frp bacon.js

我有一个表单,其中有许多图像网址 - 后端持久保存网址字符串,图像直接上传到S3.我想在上传过程中使用Bacon.js流来处理禁用/启用表单的提交按钮.

我尝试过各种方法(使用一系列Bacon.fromPromises流,使用fromPromise -d deferreds流和一个原始延迟总线并尝试手动区分两者)但是没有找到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);
});
Run Code Online (Sandbox Code Playgroud)

小提琴

*更新

@ 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);
    });
Run Code Online (Sandbox Code Playgroud)

更新小提琴

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

Ed *_*lot 5

如果您知道要上传的网址数量,可以skip像这样添加以忽略除最后一个网址之外的所有响应.

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);
});
Run Code Online (Sandbox Code Playgroud)

我发现你发布的代码有点令人担忧的一件事是这些流永远不会终止.您可以考虑重构,以便clickSearch创建proceedSearch,并在所有流完成后终止.(例如,merge上传流并重新启用该onEnd合并中的按钮.)


mjs*_*600 1

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