Promise新手求助:如何正确编写根据Item ID查询关联ItemType的代码
关于Promise实现物品类型查找的问题
我是Promise新手,写代码时遇到困惑,需要实现以下功能:
- 获取Promise返回的物品类型列表
- 遍历所有物品类型,通过Promise检查是否存在指定ID的物品
- 存在则返回该类型,不存在则不处理
当前实现代码
public getItemTypeFromItemId(itemId: string): Promise<ItemTypeName[]> { console.log("Searching for ID " + itemId + " in all item types"); return this.getItemTypes().then(itemtypes => { console.log("Found " + itemtypes.length + " item types.") let itemtypenames: ItemTypeName[] = []; const calls = itemtypes.map(itemtype => { console.log("Looking in " + itemtype.name); return this.getItemById(itemtype.name, itemId).then(value => { if (value !== undefined) { console.log("FOUND " + itemId + " within " + itemtype.name); itemtypenames.push(itemtype.name as ItemTypeName); } }); }); return Promise.all(calls).then(() => itemtypenames); }); }
自动测试用例
const PART_ID = "2A1499A5563349DAA1597EFB375FA8F2"; const CAD_ID = "24FCC02F8BD048C5881E1C63DAFC88BB"; describe('"getItemTypeFromItemId": get ItemType from item ID', async function () { it('Finds the good item type when the ID is present', async function () { await itemTypeService.getItemTypeFromItemId(PART_ID).then(itemtypenames => expect(itemtypenames[0]).to.equal("Part")); await itemTypeService.getItemTypeFromItemId(CAD_ID).then(itemtypenames => expect(itemtypenames[0]).to.equal("CAD")); }); it('Returns `undefined` if no item with this ID exists', async function () { await itemTypeService.getItemTypeFromItemId("").then(itemtypenames => expect(itemtypenames.length).to.equal(0)); }); });
优化后的实现方案
你的代码逻辑是正确的,但可以通过避免外部变量、利用Promise返回值让代码更简洁易读,同时符合Promise最佳实践。
方案1:基于then链式调用的优化
public getItemTypeFromItemId(itemId: string): Promise<ItemTypeName[]> { console.log(`Searching for ID ${itemId} in all item types`); return this.getItemTypes().then(itemtypes => { console.log(`Found ${itemtypes.length} item types.`); // 每个Promise调用返回找到的类型名或undefined const checks = itemtypes.map(itemtype => { console.log(`Looking in ${itemtype.name}`); return this.getItemById(itemtype.name, itemId).then(value => { if (value !== undefined) { console.log(`FOUND ${itemId} within ${itemtype.name}`); return itemtype.name as ItemTypeName; } // 没找到则返回undefined return undefined; }); }); // 等待所有检查完成后,过滤掉undefined的项 return Promise.all(checks).then(results => results.filter(Boolean) as ItemTypeName[]); }); }
方案2:使用async/await更直观(推荐新手使用)
async/await语法可以让异步代码看起来像同步代码,更易理解:
public async getItemTypeFromItemId(itemId: string): Promise<ItemTypeName[]> { console.log(`Searching for ID ${itemId} in all item types`); const itemtypes = await this.getItemTypes(); console.log(`Found ${itemtypes.length} item types.`); const results: ItemTypeName[] = []; // 遍历每个类型,逐个检查 for (const itemtype of itemtypes) { console.log(`Looking in ${itemtype.name}`); const item = await this.getItemById(itemtype.name, itemId); if (item !== undefined) { console.log(`FOUND ${itemId} within ${itemtype.name}`); results.push(itemtype.name as ItemTypeName); } } return results; }
如果需要保持原代码的并行检查性能,async/await版本也可以这样写:
public async getItemTypeFromItemId(itemId: string): Promise<ItemTypeName[]> { console.log(`Searching for ID ${itemId} in all item types`); const itemtypes = await this.getItemTypes(); console.log(`Found ${itemtypes.length} item types.`); const checks = itemtypes.map(async itemtype => { console.log(`Looking in ${itemtype.name}`); const item = await this.getItemById(itemtype.name, itemId); return item ? (itemtype.name as ItemTypeName) : undefined; }); const results = await Promise.all(checks); return results.filter(Boolean) as ItemTypeName[]; }
优化说明
- 去掉了外部数组
itemtypenames的副作用,直接通过Promise返回值传递结果 - 使用
filter(Boolean)快速过滤掉undefined的项,代码更简洁 - async/await版本逻辑更线性,适合新手理解和调试
- 两种优化方案都能通过你的测试用例
内容的提问来源于stack exchange,提问作者Fla
相关产品推荐
相关产品推荐

