NEAR AssemblyScript合约PersistentUnorderedMap使用及初始化后存储不显示问题
问题根因
这个现象是NEAR AssemblyScript SDK的持久化结构序列化规则和PersistentUnorderedMap的懒初始化特性导致的,具体原因如下:
PersistentMap的结构非常简单,仅包含_elementPrefix这一个实例属性,你在构造函数中完成实例化时该属性就已经被赋值,所以合约状态序列化时会直接把它写入存储PersistentUnorderedMap为了支持遍历、长度查询等能力,内部需要额外维护_keys(键列表)、_values(值列表)、_length(元素个数)三个辅助属性,这些属性默认只有在第一次执行写入操作时才会被初始化赋值,空的PersistentUnorderedMap实例在序列化时会被判定为无有效属性,所以不会出现在返回的状态结构中
这个情况不影响PersistentUnorderedMap的正常功能,只要你第一次调用set方法写入数据后,它的完整结构就会自动出现在合约存储里。
正确使用PersistentUnorderedMap的方式
基础规则
- 实例化时传入的前缀必须和合约内其他所有持久化结构的前缀唯一,避免存储冲突,你当前代码里的前缀
pma是符合要求的 - 不需要强制要求初始化阶段就出现在存储中,正常执行业务写入逻辑后它会自动完成存储初始化
- 不要手动修改
PersistentUnorderedMap的内部属性,所有操作都通过官方提供的API执行
常用操作示例
// 写入数据 this.vehicleOwnersPmap.set( "account-id.testnet", new VehicleOwner("account-id.testnet", "2024-05-20") ); // 读取数据,第二个参数为不存在时返回的默认值 const owner = this.vehicleOwnersPmap.get("account-id.testnet", null); // 判断键是否存在 const hasOwner = this.vehicleOwnersPmap.contains("account-id.testnet"); // 获取所有键/所有值 const allOwners = this.vehicleOwnersPmap.values(); const allAccounts = this.vehicleOwnersPmap.keys(); // 删除数据 this.vehicleOwnersPmap.delete("account-id.testnet"); // 获取元素个数 const count = this.vehicleOwnersPmap.length;
特殊场景处理
如果业务要求初始化阶段就必须在存储中看到PersistentUnorderedMap的结构,可以在构造函数中写入一条临时占位数据后再删除,即可触发存储初始化:
constructor(public vehicle:string = 'Mini') { this.vehicleOwners = new PersistentMap<AccountId, VehicleOwner>("vo"); this.vehicleOwnersPmap = new PersistentUnorderedMap<AccountId,VehicleOwner>("pma"); // 触发存储初始化 const tempAccount = "init_placeholder" as AccountId; this.vehicleOwnersPmap.set(tempAccount, new VehicleOwner(tempAccount, "")); this.vehicleOwnersPmap.delete(tempAccount); }
内容的提问来源于stack exchange,提问作者andy-dev
相关产品推荐
相关产品推荐

