使用Bacon.js禁用提交按钮,而延迟是"待定"

时间:2015-07-13 21:28:49

标签: javascript jquery frp bacon.js

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

我尝试了各种方法(使用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

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

2 个答案:

答案 0 :(得分:5)

如果您知道要上传的网址数量,可以像这样添加public static Node<Integer> kReverseLinkedList(Node<Integer> head, int k, int size) { if(size<k) { return ReverseLinkedList.reverseLinkedList(head); } Node<Integer> temp = head; int i=1; while(i<k) { temp = temp.next; i++; } Node<Integer> newHead = temp; temp.next=null; ReverseLinkedList.reverseLinkedList(head); Node<Integer> smallerHead = kReverseLinkedList(head.next, k, size-k); head.next = smallerHead; return newHead; } 来忽略除最后一个网址之外的所有网址的响应。

skip

我发现您发布的代码有点令人担忧的一件事是这些流永远不会终止。您可以考虑重构,以便clickSearch创建proceedSearch,并在所有流完成后终止。 (例如,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中的按钮。)

答案 1 :(得分:1)

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