【问题标题】:Why is .then() not executing at all for my Promise?为什么 .then() 根本不执行我的 Promise?
【发布时间】:2021-04-24 22:40:17
【问题描述】:

我有一个要运行的承诺链,当它完成时,我 resolve 承诺(请参阅下面的代码以获取更多上下文),并期望我的 .then() 块运行......但它确实不是。 这是我的代码:


function notifications_for_each_in_array(iteration, the_array, error_array) {
    
    return new Promise(function(resolve, reject) {

        if(!iteration) iteration = 0;
        var error_array = error_array || [];

        var user_id = the_array[iteration];

        $.ajax({
            url: ".....my_url.....",
            type: "PUT",
            data: JSON.stringify({test: [user_id]}),
            success: function() {
                // ...
            }

        }).done(function(rez) {
            error_array.push(rez);

            iteration++;

            console.log("will stop: " + (the_array[iteration] == undefined));

            if(the_array[iteration] == undefined) { // reached the end
                console.log("Resolving...");
                resolve(error_array);
            } else {
                if(the_array[iteration] != undefined) {
                    console.log("Next: " + iteration);
                    notifications_for_each_in_array(iteration, the_array, error_array);
                } 
            }
            
            
        }).fail(function(err) {
            console.error(err);
        });
    });
}

上面的函数可以工作,但是当我用.then() 调用它时,.then() 块不会运行。 在此示例中,我从未收到警报(PS:我还尝试将notifications_for_each_in_array 定义为async 函数,并使用await,但得到相同的结果):

notifications_for_each_in_array(0, [0,1,2,3], [])
.then(function(res) {
    alert("here is then()"); // I never get alerted!
});

【问题讨论】:

  • 你递归调用notifications_for_each_in_array(iteration, the_array, error_array),但不要resolve它。
  • 警告$.ajax 返回一个thennable,你有explicit constructor antipattern here
  • 您可能不想同时拥有success 回调和done 回调
  • @SebastianSimon 是正确的。另外,我不确定这里是否需要递归。似乎这段代码比它需要的更复杂。
  • @AlphaHowl 但这是解决一个不同的承诺,而不是顶级承诺。

标签: javascript asynchronous promise request resolve


【解决方案1】:

您的代码是不必要的复杂。基本上你需要做的就是遍历输入数组并使用 async/await 来运行它们。

这是一个演示,演示了在循环中执行此操作应该多么容易。你的$.ajax 调用支持 async/await,如我对 httpbin 的假调用所示。另请注意,我从未明确创建新的Promise,这一切都是通过将函数声明为async 为您完成的。

async function notifications_for_each_in_array(arr) {
  const errors = [];
  for(var i=0;i<arr.length;i++) {  
     var result = await makeAjaxCall(arr[i]);
     errors.push("response from:" + result.args.id);
  }
  return errors;
}

const makeAjaxCall = (data) => {
  return $.ajax({
    url:"https://httpbin.org/get?id=" + data,
    method:"GET",
    type:"JSONP"
  })
}

const demo = async () => {
  var result = await notifications_for_each_in_array([0,1,2,3]);
  console.log(result);
}

demo()
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"&gt;&lt;/script&gt;

您还应该注意,实际上不需要在执行下一个 http 调用之前等待每个 http 调用。你可以让它们全部并行!

async function notifications_for_each_in_array(arr) {
  const errors = await Promise.all(
    arr.map(async data => {    
      const res = await makeAjaxCall(data)
      return "response from: " + res.args.id;    
    })
  );
  
  return errors;
}

const makeAjaxCall = (data) => {
  return $.ajax({
    url:"https://httpbin.org/get?id=" + data,
    method:"GET",
    type:"JSONP"
  })
}

const demo = async () => {
  var result = await notifications_for_each_in_array([0,1,2,3]);
  console.log(result);
}

demo()
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"&gt;&lt;/script&gt;

【讨论】:

  • 是的,这行得通!我的代码确实太复杂了,谢谢!
  • @AlphaHowl,不客气。另一件需要注意的是,您不需要将每个 http 调用串联起来,您可以并行进行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-12-28
  • 1970-01-01
  • 2019-06-27
  • 2013-09-13
相关资源
最近更新 更多