简体   繁体   English

Promise allSettled 不等待承诺解决

[英]Promise allSettled not waiting for promises to resolve

I have a function that posts various updates to the server using ajax. I need to let the user know once all of the updates have been sent to the server.我有一个 function,它使用 ajax 将各种更新发布到服务器。一旦所有更新都发送到服务器,我需要让用户知道。

I have an array of promises then use promise.allSettled then but it seems to continue even though many of the promises are still pending.我有一系列的承诺,然后使用 promise.allSettled,但它似乎继续,即使许多承诺仍然悬而未决。

  $('#updateModal').modal('show');
  console.log('Sending Updates To Server');
  let DBOpenRequest = window.indexedDB.open('pending-updates');
  var promises=[];
  var recordsToDelete=[];
  DBOpenRequest.onsuccess = function(event)
  {
    var db = event.target.result;
    // db transaction
     var itemUpdatePromises = [];
     itemUpdatesTransaction = db.transaction('item-updates', 'readwrite'),
     // get object store
     itemUpdates = itemUpdatesTransaction.objectStore('item-updates'),
     // get all records in object store
     itemUpdatesRecords = itemUpdates.getAll();
     itemUpdatesRecords.onsuccess = () =>
     {
       if (typeof itemUpdatesRecords.result!=='undefined')
       {
         if (itemUpdatesRecords.result.length>0)
         {
           recordsToDelete['itemUpdates']=itemUpdatesRecords.result;
           console.log('Sending '+itemUpdatesRecords.result.length+' Item Updates To Server');
            addElement('logWindow', '<p>Sending '+itemUpdatesRecords.result.length+' Item Updates To Server  <i id="itemUpdateIcon" class="fa-duotone fa-paper-plane"></i></p>')
           $.each(itemUpdatesRecords.result, function( index, value )
           {
             var promise = postItemUpdates(value);
             promises.push(promise);
           });
         }
       }
     };
     itemUpdatesRecords.onerror = () =>
     {
      //db.close;
      console.log('Item Updates Object Store Not Found', itemUpdatesRecords.error);
     };

The code above is building the promises array.上面的代码正在构建 promises 数组。 But looking at the console output in the screenshot im getting the "all updates sent" log message before even "sending 2 item updates to server".但是查看屏幕截图中的控制台 output,我什至在“向服务器发送 2 个项目更新”之前收到“已发送所有更新”日志消息。

await delay(500); // this allowed the time for the promises array to populate before continuing - not an ideal solution but solved my issue.
console.log("before", promises.join(","))
Promise.allSettled(promises).then(function (values)
{
  console.log("after", values.join(","));
 const rejected = values.filter(result => result.status === 'rejected').map(result => result.reason);
 if ((Array.isArray(rejected) && rejected.length > 0) || typeof rejected === 'undefined')
 {
   errorMsg('There Was A Problem Sending Updates To Server');
 }
console.log('all updates sent')

在此处输入图像描述 The screenshot above is the console.log of the promises i am waiting to be resolved.上面的屏幕截图是我正在等待解决的承诺的 console.log。 The console.log(values) in the then function are empty and the success message fires straight away even though the promises are still pending.然后 function 中的 console.log(values) 是空的,成功消息会立即触发,即使 promises 仍然悬而未决。 Does anyone know why the then function is firing before the promises are settled?有谁知道为什么 function 在承诺达成之前就开火了?

The output you're seeing is the first console.log statement, before the .allSettled .您看到的 output 是第一个console.log语句,在.allSettled之前。

Remove that first log statement, and then see what you get.删除第一个日志语句,然后看看你得到了什么。


Some advice about debug logging关于调试日志记录的一些建议

You are having trouble figuring out what your program is doing, and that trouble is made worse because you're being lazy about debug logging.你很难弄清楚你的程序在做什么,而且这个问题变得更糟,因为你对调试日志记录很懒惰。

The fact is that when you're suddenly running into trouble, that's the time to become more meticulous rather than less: if you're stuck, it's probably because you misunderstood something, and the only way out of that situation is to become very careful and alert and precise while probing the situation.事实上,当你突然遇到麻烦时,是时候变得更加谨慎而不是更少:如果你陷入困境,可能是因为你误解了某些事情,而摆脱这种情况的唯一方法就是变得非常小心在探查情况时保持警惕和准确。 Put another way: if you overlooked something in haste while writing the original code, you are probably going to overlook the solution if you conduct the search with the same haste.换句话说:如果您在编写原始代码时匆忙地忽略了一些东西,那么如果您以同样的速度进行搜索,您可能会忽略解决方案。

This is what's wrong:这是错误的:

  • console.log(promises) on line 1第 1 行的console.log(promises)
  • console.log(values) on line 3第 3 行的console.log(values)

Those log statements do not contain any information other than the raw value they're dumping, which means that if they contain information you are not expecting or do not recognize, you will be unable to make sense of what you see in the logs at runtime.这些日志语句不包含它们转储的原始值以外的任何信息,这意味着如果它们包含您不期望或不认识的信息,您将无法理解您在运行时在日志中看到的内容.

Remember that console.log does not show you the name of the variable you dumped -- it only shows you the value.请记住, console.log不会向您显示您转储的变量的名称——它只会向您显示值。 So, if somehow both promises and values have the same value assigned to them, then the log statements will look identical.因此,如果以某种方式promisesvalues分配了相同的值,那么日志语句将看起来相同。

These log statements are not clear enough to guarantee that you interpret them correctly at runtime, and that is completely your fault.这些日志语句不够清晰,无法保证您在运行时正确解释它们,这完全是您的错。

I call this "lazy" because the solution to this problem is not hard to conceive of.我称之为“惰性”,因为这个问题的解决方案并不难想象。 You should just do this:你应该这样做:

  • console.log('promises', promises) on line 1第 1 行console.log('promises', promises)
  • console.log('values', values) on line 3第 3 行console.log('values', values)

The only reason most devs don't do that every time is because it requires more effort, and we all avoid extra effort.大多数开发人员不会每次都这样做的唯一原因是因为它需要更多的努力,而我们都避免了额外的努力。

So let's talk about effort.那么让我们谈谈努力。

Which of these two options takes more effort:这两个选项中哪个需要更多的努力:

  • Option A: writing minimal debug statements that are not helpful enough to lead you to the answer, so you retry the experiment with more unhelpful log statements a few times hoping it will eventually become clear, and when it doesn't, going to StackOverflow to post a question with sample code and then waiting for other people to diagnose the problem选项 A:编写最少的调试语句,这些语句不足以引导您找到答案,因此您使用更多无用的日志语句重试几次希望它最终会变得清晰,如果没有,请转到 StackOverflow 以使用示例代码发布问题,然后等待其他人诊断问题
  • Option B: writing slightly longer debug statements that print both the value of the variable and its name , so that your log statements are so unambiguous that they probably reveal the core problem on the first test run选项 B:编写稍微长一点的调试语句,打印变量的值及其名称,这样您的日志语句就会非常明确,以至于它们可能会在第一次测试运行时揭示核心问题

This is not a trick question.这不是一个技巧问题。 Option A takes more effort.选项A需要更多的努力。 It always takes more effort.它总是需要更多的努力。 The reason most developers choose Option A is that the first step of Option A is slightly less effort that the first step of Option B;大多数开发人员选择方案 A 的原因是方案 A 的第一步比方案 B 的第一步稍微省力; nevermind that Option B has only one step .没关系,选项 B只有一个步骤 (Gradient descent affects biological intelligence, too!) (梯度下降也会影响生物智力!)


The reason I mentioned earlier that this problem is "your fault" is not to make you feel bad, but because it's important to recognize that this means things will only get better if you change your methods .我之前提到这个问题是“你的错”的原因并不是让你感觉不好,而是因为重要的是要认识到这意味着只有你改变你的方法事情才会变得更好 The bad experience you're having is not the result of faulty technology or shoddy tools.您遇到的糟糕体验并非技术故障或劣质工具造成的。 You have amazing tech and tools at your disposal.您拥有惊人的技术和工具供您使用。 You're getting bad results because you're not using them well.你得到不好的结果是因为你没有很好地使用它们。 Start using them well, and you will start getting better results.开始好好使用它们,您将开始获得更好的结果。

I did my logging just like your code sample for nearly 20 years, and although I was never so hopelessly stuck that I posted about it online, the truth is that, just like you, I often found the log results perplexing.我像您的代码示例一样进行了近 20 年的日志记录,虽然我从来没有像我在网上发布的那样无可救药地陷入困境,但事实是,就像您一样,我经常发现日志结果令人困惑。

Then one day I started doing all my debug logging like this:然后有一天,我开始像这样进行所有调试日志记录:

console.log(`someVar`, JSON.stringify(someVar))

Note:笔记:

  • prints the variable name first首先打印变量名
  • stringifies the value字符串化值

It's hard to overstate the impact this one tiny change had on my day-to-day experience.很难夸大这一微小变化对我日常体验的影响。 From that point forward, debug logging has become an extremely reliable tool.从那时起,调试日志记录已成为一种极其可靠的工具。 I don't always have to resort to debug logging to figure out a problem, but now I can almost always count on it to find the problem in a single test run .我不必总是求助于调试日志来找出问题,但现在我几乎总是可以指望它在一次测试运行中找到问题。

Of course, I am also a very lazy person, and so eventually I got tired of writing all that out.当然,我也是一个很懒惰的人,所以最后我也懒得写了。 I still did it every time because it was so important, but it bothered me.我仍然每次都这样做,因为它非常重要,但它困扰着我。

It turns out that many IDEs have sophisticated code-completion features.事实证明,许多 IDE 都具有复杂的代码完成功能。 So, unless you're doing all your coding with Notepad, you can probably do what I did and set up a snippet.因此,除非您使用记事本完成所有编码,否则您可能可以像我一样做并设置一个片段。 Here's mine, in VS Code.这是我的,在 VS Code 中。 It triggers when I type dump and then hit Tab:当我输入dump然后点击 Tab 时它会触发:

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM