Promise.allSettled 中的 Promise 数组的顺序以及创建数据库事务的顺序?

2023-12-29

在下面的代码中,

Promise.allSettled( [ entry_save(), save_state(), get_HTML() ] ).then( ... );

承诺entry_save and save_state都是readwrite数据库事务和get_HTML is readonly。他们俩readwrite事务可以组合在一起,但这会使维护的撤消/重做链变得复杂,并将两者的成功和回滚联系在一起,这是不希望的。

The entry_save交易需要在之前写入save_state交易。搬家前entry_save进入Promise.allSettled这就是它的工作原理,因为entry_save交易是先于其他交易创建的。这MDN 文章 https://developer.mozilla.org/en-US/docs/Web/API/IDBTransaction解释了请求执行的顺序如何取决于创建事务的时间,而与发出请求的顺序无关。

我的问题是每个 Promise 进程的同步代码是否按照其放置在数组中的顺序进行,以便放置entry_save首先总是会导致首先创建其事务并保证首先执行其数据库请求?

虽然它有效并且足够快,但我不想这样做:

entry_save().then( () => { Promise.allSettled( [ save_state(), get_HTML() ] ) } ).then( ... );

如果重要的话,这并不完全是这样写的,它更符合:

entry_save().then( intermediate ); where intermediate调用Promise.allSettled.

谢谢。

为了澄清一点,下面是上面引用的 MDN 文档中给出的示例。

var trans1 = db.transaction("foo", "readwrite");
var trans2 = db.transaction("foo", "readwrite");
var objectStore2 = trans2.objectStore("foo")
var objectStore1 = trans1.objectStore("foo")
objectStore2.put("2", "key");
objectStore1.put("1", "key");

After the code is executed the object store should contain the value "2", since trans2 should run after trans1.

If entry_save创造trans1 and save_state create trans2,并且全部在函数的同步代码中,这意味着不在一个函数内onsuccess or onerror数据库请求的处理程序或类似的东西,MDN 示例不成立吗?

因此,@jfriend00 写道,

这些函数按照它们在数组中的放置顺序被调用, 但这仅决定了异步的顺序 开始了。

由于事务是在异步代码开始之前在同步代码中创建的,因此这是否会按照事务创建的时间顺序对写入请求进行排序?

我想测试一下,但我不知道如何测试。如果两个几乎相同的 Promise 被用在一个Promise.allSettled,如何延迟第一个创建的事务的写入请求,使其发生在第二个创建的事务的写入请求之后,以测试是否会先写入? setTimeout 应该终止事务。也许在请求之前放置了一个长时间运行的同步循环。


这个问题最后的代码可能会更好地更准确地说明我试图问的问题。它采用上面引用的文章中的 MDN 示例,并将其分布在两个承诺中Promise.allSettled,两者都尝试从内部写入同一对象存储onsuccess的事件get要求。

问题是,在创建第二个事务之前创建的第一个事务的文章中的相同原理,无论请求的顺序如何,仍然适用于此设置。由于 Promise 的同步部分将按照 Promise 放置在数组中的顺序进行处理,因此 Promise 中的事务p_1将在之前创建p_2。但是,那put请求在onsuccess事件的get请求在p_1由于构建大字符串的循环而延迟。问题是意愿p_1还是之前写的p_2?

在尝试这个时,我无法得到p_2写在之前p_1。因此,看来 MDN 示例甚至适用于此类设置。但是,我无法确定为什么,因为我不明白 JS 代码是如何真正解释/处理的。

例如,为什么可以req.onsuccess请求发出后定义函数?我问的是question https://stackoverflow.com/questions/51394399/why-are-indexeddb-requests-made-before-the-event-handlers-are-declared不久前但仍然不知道它不会影响我尝试在此处添加延迟的方式。我知道反过来是行不通的;但我的观点是我不确定浏览器在发出 put 请求之前如何处理该同步循环p_1真正确定这个示例表明 MDN 文章始终适用于此设置。但是,我可以观察到,随着循环迭代次数的增加,完成请求需要更长的时间;而且,在我观察到的所有情况下,p_1总是写在前面p_2。唯一的办法p_2写在之前p_1 is if p_1根本不写入,因为字符串占用了太多内存,导致事务在p_1被中止。

话虽这么说,回到我的问题的更完整的设置,涉及一系列的三个承诺Promise.allSettled与要求相比entry_save在开始之前完成Promise.allSettled关于剩下的两个承诺,在我的项目的完整代码中,出于我不确定的原因,后者比前者更快,即等待entry_save完成比将其包含在中更快Promise.allSettled.

我原以为情况会相反。我现在能想到的唯一原因是,因为entry_save and save_state都写入同一个对象存储,也许浏览器所做的任何事情都相当于锁定对象存储直到第一个事务,即entry_save,完成并移除锁所需的时间比要求的时间长entry_save之前完成Promise.allSettled开始并且不涉及锁。本以为一切都会“提前”准备好,只等两人put请求按交易顺序进行。它们按顺序发生,但速度较慢,或者至少不如使用以下命令那么快:

entry_save().then( () => { Promise.allSettled( [ save_state(), get_HTML() ] ) } ).then( ... );

代替:

 Promise.allSettled( [ entry_save(), save_state(), get_HTML() ] ).then( ... );

function p_all() { Promise.allSettled( [ p_1(), p_2() ] ); }

function p_1()
  {
    return new Promise( ( resolve, reject ) =>
      {
        let T = DB.transaction( [ 'os_1', 'os_2' ], 'readwrite' ),
            q = T.objectStore( 'os_1' ),
            u = T.objectStore( 'os_2' ),
            req, i, t ='', x = '';    

     req = q.get( 1 );

     req.onsuccess = () =>
       {
         let i, t, r = req.result;
         for ( i = 1; i < 10000000; i++ ) t = t + 'This is a string';
         r.n = 'p1';
         u.put( r );
         console.log( r );
       };
    }); }

function p_2()
  {
    return new Promise( ( resolve, reject ) =>
      {
       let T = DB.transaction( [ 'os_1', 'os_2' ], 'readwrite' ),
           q = T.objectStore( 'os_1' ),
           u = T.objectStore( 'os_2' ),
           req;    

        req = q.get( 1 );

        req.onsuccess = () =>
          {
            let r = req.result;
            r.n = 'p2';
            u.put( r );
            console.log( r );
          };
    }); }

indexedDB 将按照创建的顺序维护事务的顺序,除非这些事务不重叠(例如,不涉及每个事务涉及的一组存储中的相同存储)。这几乎与您在更高的承诺层做什么无关。

同时,依赖这种行为也许是不明智的,因为它是隐含的并且有点令人困惑。所以也许用承诺来线性化是可以的。唯一的问题是当你需要最大性能时,我怀疑这是否适用。

  • see https://www.w3.org/TR/IndexedDB-2/#transaction-construct https://www.w3.org/TR/IndexedDB-2/#transaction-construct
  • see indexeddb/localforage 读取是否从同步缓冲区解析? https://stackoverflow.com/questions/54956481

此外,承诺在创建时就开始执行。它们只是不一定在那一刻结束,它们最终会结束而不是立即结束。这意味着调用按照您“创建”包装 indexedDB 调用的承诺的顺序发生。这意味着它依赖于您创建交易的顺序。

无论哪个承诺赢得了比赛。无论使用promise.all。

另外,即使 Promise 不按顺序完成,promise.all 也会保留顺序,仅供参考,但不要让它让你失望。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Promise.allSettled 中的 Promise 数组的顺序以及创建数据库事务的顺序? 的相关文章

  • 浏览器视口大小(以设备像素为单位)

    Goal 我希望 Flash 能够获得有关浏览器视口宽度和高度 以设备像素为单位 的准确信息初始化 调整大小或浏览器缩放事件时 规格 我需要将 flash 嵌入到在 chrome safari firefox 等中运行的 html 页面中
  • 位置特征检测:固定

    我正在尝试找到一个脚本来检测设备是否放置position fixed元素相对于视口而不是整个文档 目前 标准桌面浏览器和 Mobile Safari 适用于 iOS 5 都是这样做的 而 Android 设备则相对于整个文档放置固定元素 我
  • 使用 Node.js 构建网站的最佳实践

    这个问题的答案是社区努力 help privileges edit community wiki 编辑现有答案以改进这篇文章 目前不接受新的答案或互动 我想知道如何使用 Node js 从头开始 开发一个网站 我明白我怎么能possibly
  • 在版本 4.4.6 中禁用 ckeditor 上下文菜单

    我在 Rails4 项目中使用 ckeditor 我尝试了 ckeditor gem 和 ckeditor rails gem 来提供 ckeditor 库 这里有多个帖子 人们希望删除 ckeditor 上下文菜单 以便可以显示本机浏览器
  • 为什么 window 与 Internet Explorer 中的 window.self 不同?

    关于我如何遇到这个问题有一个复杂的背景故事 但为什么self属性不完全等于窗口本身 在 Safari 和 Firefox 及其朋友中 结果如我所料 gt window window self true gt window window se
  • Number.IsNaN() 比 isNaN() 更糟糕吗

    Soooooo isNaNJavaScript 显然被破坏了 比如 isNaN isNaN isNaN true isNaN false isNaN 0 返回 false 当它们看起来都是 不是数字 在 ECMAScript 6 中 草案包
  • 通过 JavaScript 获取表单名称

    我有一个简单的问题 但我在网上找不到好的解决方案 我有这个 HTML 代码
  • 想要动态处理与分页相关的页码显示:ReactJS

    我有一些分页逻辑工作得很好 唯一的问题是我只能让它显示并固定数量的页面可供选择 现在我已经把它放到了 5 页 但我希望它能够根据总记录动态更改 假设我有 100 条记录 每页限制为 10 条 将有 10 页 现在我只能让它以这种方式显示 第
  • 如何使用 Greasemonkey 监视静态 HTML 页面的更改?使用哈希?

    我希望我的 Greasemonkey 脚本仅在其访问的静态页面具有与以前完全相同的内容时运行 现在我可以设置一个包含该页面哈希的变量 我正在寻找一种动态散列页面的方法 以便我可以将我的散列与生成的散列进行比较 关于如何即时实现散列的任何想法
  • React Router v4 不渲染组件

    React Router v4 渲染组件存在问题 在应用程序初始加载时 它将呈现与 URL 相对应的正确组件 但是 任何后续的组件Link单击不会呈现所需的组件 图书馆 反应路由器 4 2 2 https reacttraining com
  • JavaScript推送函数中的动态变量

    我在 JavaScript 中使用推送功能 var chartData for var i 0 i lt 3 i chartData push date new Date year s mon s date s hr s min s sec
  • 将 Firebase 云消息传递与 Windows 应用程序结合使用

    我在 Android 和 iOS 应用程序中使用 Firebase Cloud Messaging 但是我还有此应用程序的 Windows Mac OS 版本 我想保留相同的逻辑 我知道 Firebase Cloud Messaging 可
  • mongodb 聚合 - 累积字段的不同组值

    如果我有Player表格文件 name String score Int 我有Group文档 其中组代表玩家列表 groupName String players ObjectID 玩家可以属于多个组 我想做一个聚合Player文档 按以下
  • 如何正确取消引用然后删除 JavaScript 对象?

    我想知道从内存中完全取消引用 JavaScript 对象的正确方法 确保删除时不会在内存中悬空 并且垃圾收集器会删除该对象 当我看这个问题时在 JavaScript 中删除对象 https stackoverflow com questio
  • JavaScript eval("{}") 返回行为?

    根据ECMA 262 规范 http www ecma international org publications files ECMA ST Ecma 262 pdf 以下语句返回1 eval 1 eval 1 eval 1 var a
  • 使用javascript动态更新css内容

    需要将 css 更新为动态值 我不确定最好的方法是什么 div style zoom 1 div 缩放级别将根据窗口大小调整触发 应用程序将相应缩放 我将此应用程序加载到 cordova 中并让它在 iPAD 中运行 然后我意识到需要使用
  • 使用 Jade 评估自定义 javascript 方法 (CircularJSON)

    我想通过 Jade 将一个对象解析为客户端 JavaScript 通常这会起作用 script var object JSON parse JSON stringify object but my object is circular ht
  • $resource.query 返回分割字符串(字符数组)而不是字符串

    我正在使用像下面这样的 Angular resource angular module app factory data function resource var Con resource api data update method P
  • Flot 库将 y 轴设置为最小值 0 和最大值 24

    如何将 y 轴设置在 0 到 24 的范围内 这是我的代码 j plot j placeholder d1 xaxis mode time min new Date 2010 11 01 getTime max new Date 2011
  • 如何从 json 文件创建模型? (ExtJS)

    这是我想使用 json 文件创建的模型 Ext define Users extend Ext data Model fields name user id type int name user name type string 为了根据服

随机推荐