如何用ES6简洁方式从对象数组匹配属性并获取目标属性值
Hey there! Let's fix up this code to be cleaner, more robust, and fully leverage ES6+ async/await features—goodbye messy nested .then() calls and unsafe array access!
First, let's break down the issues with your current code:
- Nested
.then()creates "callback hell" which hurts readability - Accessing
nameMatchExactlyArray[0]without checking if the array has items will throw a runtime error if no matches are found for await...ofis unnecessary here unlessjsonis an async iterator (for a regular array, plainfor...ofworks fine withawait)
Here's a refactored, idiomatic version that fixes all these problems:
async function processItems(json) { for (const item of json) { try { // Replace .then() with await for linear, readable code const search1Results = await searchNumber1(item.property1); // Use find() instead of filter()[0]—it's more efficient (stops at first match) and cleaner const matchedApiItem = search1Results.find(apiItem => apiItem.name === item.property1); // Handle the case where no match is found (critical for avoiding crashes!) if (!matchedApiItem) { console.warn(`No matching item found for name: ${item.property1}`); continue; // Skip to the next item instead of breaking } // Run the second search with the matched ID, again using await const search2Results = await searchNumber2(matchedApiItem.id); // Do whatever you need with the second search results here console.log(`Search #2 results for ${item.property1}:`, search2Results); } catch (error) { // Catch errors for individual items so one failure doesn't break the whole loop console.error(`Failed to process item ${item.property1}:`, error); } } }
Key improvements explained:
- Async/await instead of nested
.then(): This makes the asynchronous flow read like synchronous code, which is way easier to follow and debug. find()overfilter()[0]:filter()scans the entire array to collect all matches, whilefind()stops at the first hit—better performance, and it directly gives you the single item you need (no array index required).- Explicit null/undefined checks: We verify that
matchedApiItemexists before accessing itsidproperty, preventing annoying "Cannot read property 'id' of undefined" errors. - Per-item error handling: The
try/catchblock wraps each item's processing, so if one search fails, the rest of the loop can still run instead of crashing the whole function.
If your use case allows for parallel processing (i.e., the API calls for different items don't depend on each other), you can speed things up drastically with Promise.all():
async function processItemsInParallel(json) { // Map each item to an async processing function const processingPromises = json.map(async (item) => { try { const search1Results = await searchNumber1(item.property1); const matchedApiItem = search1Results.find(apiItem => apiItem.name === item.property1); if (!matchedApiItem) { console.warn(`No match for ${item.property1}`); return null; } return await searchNumber2(matchedApiItem.id); } catch (error) { console.error(`Error with ${item.property1}:`, error); return null; } }); // Wait for all parallel operations to complete const allSearch2Results = await Promise.all(processingPromises); // Filter out null/failed results if needed const successfulResults = allSearch2Results.filter(result => result !== null); console.log("All successful Search #2 results:", successfulResults); }
Just note: Parallel processing sends all your API requests at once, so make sure you don't hit rate limits for the API you're calling.
This approach is far more maintainable, robust, and aligned with modern JavaScript best practices.
内容的提问来源于stack exchange,提问作者Kyle Pennell

