RxJS:请求完成后再次开始发布

RxJS: Start publishing again when request is done

我正在使用 RxJS 来监听表单提交事件,并通过 AJAX 提交它(这是一段奇怪的代码,但我现在只是在试验 RxJS,所以请耐心等待).我想做的是仅在请求未进行时允许提交。

到目前为止,我的代码看起来像这样(而且是 "working"):

Rx.DOM.submit(formEl)
  .map(function(event){ event.preventDefault(); return event; })
  .map(function(){ return getEmailAddress(formEl); })
  .subscribe(function(email){
    submitToMailChimp(url, email).done(showMailChimpThanks(orbitInstance)).fail(showMailChimpError);
  });

我的问题是我不确定如何实现一些东西来适应这个限制(看到 skipUntil 但不太确定在这种情况下如何处理)。所以我的问题是:我如何 (a) 在我的 Ajax 请求完成之前阻止提交,以及 (b) 优化我的代码以使 Ajax 请求位于链的末尾,这样我就可以 subscribe 它的结果,而不是这种奇怪的混合混搭。

最终解:

var submissions = Rx.DOM.submit(formEl);

submissions.subscribe(preventDefaultEvent);

var requests = submissions
  .first()
  .map(getEmailAddress(formEl))
  .flatMap(submitToMailChimp(url))
  .catch(showMailChimpError(submitButton))
  .repeat();

requests.subscribe(showMailChimpThanks(orbitInstance, submitButton));

好问题。在 submit 之后使用 first() 只允许一次提交,并且在 ajax 请求完成后(我们将通过 flatMap 调用),这个可观察对象将完成(因为 first).因此,我们附加一个 repeat() 以在第一个提交完成后开始监听下一个提交。因为我想您不想在 ajax 调用之一失败时停止流,所以我们会将您的 ajax 请求的结果转换为 Error 或结果和流此 "Either" 作为数据(参见 this question

棘手的部分是您还想确保每次都调用 preventDefault,即使正在处理当前提交并且我们当前没有监听 submit。在我看来,这是一个具有不同观察要求的不同动作,因此我们应该将它写成一个单独的查询。因此我们最终得到:

var submissions = Rx.DOM.submit(formEl);

// send ajax requests on submissions
submissions
    .first()
    .flatMap(function (event) {
        var email = getEmailAddress(formEl);
        return submitToMailChimp(url, email)
            .then(
                function (v) { return v; },
                function (e) { return new Error(e); });
    })
    .repeat()
    .subscribe(function (result) {
        if (result instanceof Error) {
            showMailChimpError(result);
        }
        else {
            showMailChimpThanks(instance);
        }
    });

// prevent defaults
submissions.subscribe(function (ev) { ev.preventDefault(); });