自定义Iterator满足条件时无法中断迭代的问题求助
你的代码存在几个关键问题,导致找到目标Order后循环无法中断,同时还有迭代逻辑的错误:
1. 错误使用for await...of遍历同步迭代器
你的DateIncrementor实现的是同步迭代器(通过[Symbol.iterator]),但你用了for await...of来遍历。虽然JS允许这种写法,但会把同步迭代器强制包装成异步迭代器,可能导致迭代行为异常。因为你的迭代逻辑是同步的,只是内部调用了异步方法,所以应该改用普通的for...of循环,内部正常使用await即可。
2. Order类的orderItems定义错误
你把orderItems定义成了空函数:orderItems = (),而不是空集合(数组/对象)。isEmpty函数通常用来判断数组、对象这类集合是否为空,对于函数来说,它不会被判定为空值,导致!isEmpty(orderDetails.orderItems)的结果不符合预期——如果isEmpty认为函数不是空,那这个条件永远为true,理论上会触发break;但如果你的isEmpty函数把函数判定为空,那这个条件永远为false,break永远不会执行。
正确的定义应该是:
class Order { //... orderItems: any[] = []; // 或者根据实际业务类型定义为空数组/对象 }
3. DateIterator的日期迭代逻辑错误
每次调用next时,你都基于初始日期加一天,而不是基于上一次迭代的日期更新。这会导致每次返回的都是同一个日期(初始日期+1天),相当于一直在重复搜索同一天,而不是逐天递增。
修复后的DateIterator:
export class DateIterator { date: Date; limit = 15; currentCount = 0; constructor(date: Date) { // 复制传入的日期,避免修改原对象 this.date = new Date(date); } next() { // 改成<,确保最多迭代15次(currentCount从0到14) if (this.currentCount < this.limit) { // 直接更新当前日期为下一天 this.date = plusDays(this.date, 1); console.warn({currentNumberOfDays: this.currentCount}, 'Number of days iterated'); this.currentCount++; // 根据getOrdersForDate的参数要求,返回字符串或Date对象 return { done: false, value: this.date.toDateString() }; } else { return { done: true, value: this.date }; } } }
4. 冗余的条件判断
searchByDate中的if(date)判断完全冗余,因为date是函数参数,只要调用时传入有效日期,这个条件永远为true,可以直接删除。
修复后的searchByDate函数
const searchByDate = async(date: Date) => { const orderService = new OrderService(); let count = 0; let result: Order | null = null; // 改用普通for...of循环 for (let currentDate of new DateIncrementor(date)) { count++; const orderDetails: Order = await orderService.getOrdersForDate(currentDate); if (orderService.isCurrentOrder(orderDetails) && !isEmpty(orderDetails.orderItems)) { result = orderDetails; break; // 现在这个break会正常中断循环 } } console.log('Number of executions of iterator', count); return result; }
总结
修复以上问题后,当找到符合条件的Order时,break语句会正常中断循环,不会再执行到15次限制。同时日期迭代逻辑也会正确地逐天递增,避免重复搜索同一天。
内容的提问来源于stack exchange,提问作者BreenDeen

