有没有办法让jQuery的.on()函数与promises一起玩得很好?

时间:2014-10-17 21:26:58

标签: javascript jquery promise

忍受我 - 我意识到我在下面做的事情是愚蠢的,我只是无法在网上看到解决方案让我自己愚蠢:)

我有以下功能,我希望返回一个承诺:

function getInput() {
  var form = $("form.prompt"); // some form in the DOM, this is working fine
  return Promise.resolve(form.show().focus().submit(function(event) {
    var input = $(this).find("input");
    var inputVal = input.val();
    alert("form submitted! input val is " + inputVal);
    event.preventDefault();
    resolve(inputVal);
  }));
}

我调用该函数并尝试等待承诺解决:

getInput().then(function(response) {
  alert("input resolved; response is " + response);
});

我希望看到以下行为:在我提交表单之前没有提醒,之后我会看到"提交表单!"然后"输入已解决"。

相反,我看到"输入已解决"立即。 (显然,在此之后,一旦我提交表格,我就会看到"表格已提交!"。)

我意识到我完全没有正确处理.submit()函数;我对它的处理就像它是可以的,并且会被Promise.resolve()投射到一个正确的承诺中。显然,这没有发生。我认为.submit()有一些其他的值或属性,Promise.resolve()正在结束它的promise评估链,这就是then()立即执行的原因。

此外,我意识到我正在处理.submit(),好像它是一个我正在等待的单个事件,而它是一个意味着要运行的回调函数表单提交的每个时间。

我的问题是,做我想做的事情的正确方法是什么?也就是说,推迟执行某些代码(此处由"输入已解决"警报表示)直到特定表单提交一次?就像我需要一个能用短暂的超时循环的函数,直到它看到.submit()回调设置了一个标志...

3 个答案:

答案 0 :(得分:2)

我想你想要这个:

function getInput() {
  var form = $("form.prompt"); // some form in the DOM, this is working fine
  var deferred = $.Deferred();
  form.show().focus().one("submit", function(event) {
    var input = $(this).find("input");
    var inputVal = input.val();
    alert("form submitted! input val is " + inputVal);
    event.preventDefault();
    deferred.resolve(inputVal);
  });
  return deferred.promise();
}

答案 1 :(得分:1)

你完全可以做到。它可能看起来像这样:

function getInput() {
    return new Promise(function (resolve, reject) {
        var $form = $("form.prompt").on('submit', function (event) {
            var input = $form.find("input").val();
            event.preventDefault();
            resolve(input);
        });
    });
}

getInput().then(function (response) {
    alert("input resolved; response is " + response);
});

但是这个例子完美地证明Promise不是完成任务的正确工具:你只能解决或拒绝它一次。

演示:http://jsfiddle.net/q306nzk2/

答案 2 :(得分:0)

进一步采纳@dsfq的答案 -

事实证明,您可以以平坦的方式嵌套承诺,使代码更加优雅。这个技巧受到https://parse.com/docs/js_guide#promises-series的启发 - 请告诉我这是否记录了本地js承诺的任何地方!

(代码在http://jsfiddle.net/q306nzk2/6/生效)

function getInput() {
    return new Promise(function (resolve, reject) {
        var $form = $("form.prompt").one('submit', function (event) {
            var input = $form.find("input").val();
            event.preventDefault();
            resolve(input);
        });
    });
};

// start by making essentially a "blank", resolved promise:
var prm = Promise.resolve();

// next, append a function to perform, which returns a promise; 
// this will cause prm to effectively "block" until the promise 
// getInput returns is resolved
prm = prm.then(function() {
    return getInput().then(function(response) {
        alert("input resolved; response is " + response);
    });
});

// do it again -- this function won't execute until the previous promise resolves!
prm = prm.then(function() {
    return getInput().then(function(response) {
        alert("input resolved again; response is " + response);        
    });
});