diff --git a/RWPromise/Class/Internal/reduce.m b/RWPromise/Class/Internal/reduce.m index 4a83100..36c69f9 100644 --- a/RWPromise/Class/Internal/reduce.m +++ b/RWPromise/Class/Internal/reduce.m @@ -8,13 +8,20 @@ @implementation RWPromise (reduce) + (RWPromise *) reduce:(NSArray *) array :(RWReduceFuncBlock) reduceFunc initialValue:(id)initialValue { - NSMutableArray* promises = @[].mutableCopy; + if (array.count == 0) { + return nil; + } + __block RWPromise * p = reduceFunc(array[0],initialValue); [array enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { - [promises addObject:reduceFunc(obj,initialValue)]; + if (idx > 0) { + p = p.then(^id(id value){ + return reduceFunc(obj,value); + }); + } }]; - return [RWPromise all:promises].then(^id(NSArray* res){ - return res.lastObject; + return p.then(^id(id res){ + return res; }); } @end \ No newline at end of file diff --git a/RWPromiseTests/RWPromiseTests.m b/RWPromiseTests/RWPromiseTests.m index 2b9fca8..24397ee 100644 --- a/RWPromiseTests/RWPromiseTests.m +++ b/RWPromiseTests/RWPromiseTests.m @@ -249,8 +249,8 @@ - (void) testAll1 } [NSThread sleepForTimeInterval:3]; XCTAssert([result[0] isEqualToString:@"1"]); - XCTAssert([result[1] isEqualToString:@"Timeout"]); - XCTAssert([result[2] isEqualToString:@"Timeout"]); + XCTAssert([[result[1] allKeys][0] isEqualToString:@"Timeout"]); + XCTAssert([[result[2] allKeys][0] isEqualToString:@"Timeout"]); } - (void) testAll2 @@ -372,7 +372,7 @@ - (void) testTimeout2 XCTAssertNil(result); [NSThread sleepForTimeInterval:4]; - XCTAssertEqual(result, @"Timeout"); + XCTAssertEqual([result allKeys][0] , @"Timeout"); } - (void) testAfter @@ -517,4 +517,94 @@ - (void) testRetry3 XCTAssertTrue([final isEqualToString:@"hola"]); } +- (void) testMap1 +{ + __block NSArray* final = nil; + @autoreleasepool { + [RWPromise map:@[@"1",@"2",@"3"] :^RWPromise *(id value) { + return [RWPromise resolve:value]; + }].then(^id(NSArray* values){ + final = values; + return nil; + }); + } + + XCTAssertTrue([final isKindOfClass:[NSArray class]]); + XCTAssertEqual(3, final.count); + XCTAssertTrue([final containsObject:@"1"]); + XCTAssertTrue([final containsObject:@"2"]); + XCTAssertTrue([final containsObject:@"3"]); +} + +- (void) testMap2 +{ + __block id final = nil; + @autoreleasepool { + [RWPromise map:@[@"1",@"2",@"3"] :^RWPromise *(id value) { + return [RWPromise reject:value]; + }].then(^id(NSArray* values){ + final = values; + return nil; + }) + .catch(^(NSError* e){ + final = e; + }); + } + + XCTAssert([final isKindOfClass:[NSError class]]); +} + +- (void) testFilter +{ + __block NSArray* final = nil; + @autoreleasepool { + [RWPromise filter:@[@1,@2,@3,@4,@5] :^BOOL(NSNumber* number) { + return number.integerValue % 2 == 0; + }] + .then(^id(NSArray* values){ + final = values; + return nil; + }); + } + XCTAssertEqual(2, final.count); + XCTAssertTrue([final containsObject:@2]); + XCTAssertTrue([final containsObject:@4]); +} + +- (void) testReduce1 +{ + __block NSNumber* final = nil; + @autoreleasepool { + [RWPromise reduce:@[@1,@2,@3,@4,@5] :^RWPromise *(id item, NSNumber* acc) { + return [RWPromise resolve:item].then(^id(NSNumber* number){ + return @(acc.integerValue + number.integerValue); + }); + } initialValue:@(0)] + .then(^id(NSNumber* value){ + final = value; + return nil; + }); + } + XCTAssertTrue([final isEqualToNumber:@15]); + +} + +- (void) testReduce2 +{ + __block NSNumber* final = nil; + @autoreleasepool { + [RWPromise reduce:@[@1,@2,@3,@4,@5] :^RWPromise *(id item, NSNumber* acc) { + return [RWPromise resolve:item].then(^id(NSNumber* number){ + return @(acc.integerValue * number.integerValue); + }); + } initialValue:@(1)] + .then(^id(NSNumber* value){ + final = value; + return nil; + }); + } + XCTAssertTrue([final isEqualToNumber:@120]); + +} + @end