google / promises

Promises is a modern framework that provides a synchronization construct for Swift and Objective-C.
Apache License 2.0
3.8k stars 293 forks source link

Too slow #77

Closed chiragpurohit71085 closed 5 years ago

chiragpurohit71085 commented 5 years ago

I had implemented FBLPromiseAwait for firebase. It basically gets some data from firebase node and iterate for various condition. This takes around 15 seconds for 605 records, while iteration with normal firebase functions takes only 2 to 3 seconds i.e

[[[[[[FIRDatabase database] reference] child:USERS_TABLE] queryOrderedByChild:@"user_id"] queryEqualToValue:[[obj objectForKey:@"data"] objectForKey:@"user_id"]] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot){ ..........

Please help me if I am implementing anything wrong

here is my sample code FBLPromiseAwait.

` FBLPromise<NSMutableArray > promise = [FBLPromise onQueue:dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL) do:^id { NSError error; NSDictionary notifications = FBLPromiseAwait([self getSomeData], &error);

                                             NSArray*notification_keys = [notifications allKeys];

                                             for(int notification_count=0;notification_count<[notification_keys count ];notification_count++)

                                             {

                                                 NSDictionary*obj = [notifications objectForKey:[notification_keys objectAtIndex:notification_count]];

                                                 NSString *notifType = [[obj objectForKey:@"data"] objectForKey:@"type"];
                                                 NSString *timeString = [[PBDateFormatter sharedFormatter] getCustomDateStringForChat:[NSDate dateWithTimeIntervalSince1970:[[[obj objectForKey:@"data"] objectForKey:@"timestamp"] longLongValue]/1000]];
                                                 NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:[[obj objectForKey:@"notification"] objectForKey:@"title"] attributes:@{NSFontAttributeName : [UIFont fontWithName:PINGBUDS_FONT_NORMAL size:12], NSForegroundColorAttributeName : [UIColor blackColor]}];

                                                 //SOMEREFERENCE,conversation/deleteByInitiatingUser
                                                 if([notifType isEqualToString:@"SOMEREFERENCE"] || [notifType isEqualToString:@"conversation/deleteByInitiatingUser"] )
                                                 {

                                                     NSDictionary*userData = FBLPromiseAwait(
                                                                                             [FBLPromise async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {

                                                         [[[[[[FIRDatabase database] reference] child:USERS_TABLE] queryOrderedByChild:@"user_id"] queryEqualToValue:[[obj objectForKey:@"data"] objectForKey:@"user_id"]] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot){

                                                             fulfill([[snapshot.value allObjects] firstObject]);

                                                         }];

                                                     }], &error);
                                                     NSLog(@"\n promise user userData - %@",userData);

                                                     NSDictionary*skillFound = FBLPromiseAwait(
                                                                                               [FBLPromise async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {

                                                         [[[[[[FIRDatabase database] reference] child:SOME_TABLE] queryOrderedByChild:@"id"] queryEqualToValue:[[obj objectForKey:@"data"] objectForKey:@"skill_id"]] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot){

                                                             NSLog(@"\n\n obj at moment - %@",obj);

                                                             fulfill([[snapshot.value allObjects] firstObject]);

                                                         }];
                                                     }], &error);

                                                    [_dataSource addObject:model];

                                                     //Ends : SOMEREFERENCE,conversation/deleteByInitiatingUser

                                                 }

                                                 else if([components[0] isEqualToString:@"XXX"]){}
                                                 else if([notifType isEqualToString:@"YYYY"]){}
                                                 else if([notifType isEqualToString:@"zzzz"]){}
                                                 else if([notifType isEqualToString:@"pppp"]){}

                                             }

                                             dispatch_async(dispatch_get_main_queue(), ^{

                                                 [MBProgressHUD hideHUDForView:self.view animated:YES];
                                                 [self do_some_ui_stuff];

                                             });

                                             if (error) {
                                                 return error;
                                             }

                                             return _dataSource;

                                         }];`
shoumikhin commented 5 years ago

Hi @chiragpurohit71085,

I doubt that you really need to use FBLPromiseAwait at all. Normally, you should be good by simply chaining promises into pipelines, possibly with the help of misc extensions operators.

Like for your example I imagine something akin the following:

[[[self getSomeData] then:^id(NSDictionary *notifications) {
  NSMutableArray<FBLPromise *> *modelPromises = [NSMutableArray new];
  for(id key in notifications) {
    NSDictionary *notification = notifications[key];
    NSString *notificationType = notification[@"data"][@"type"];

    if ([notificationType isEqualToString:@"SOMEREFERENCE"] ||
        [notificationType isEqualToString:@"conversation/deleteByInitiatingUser"]) {
      FBLPromise<NSDictionary *> *userDataPromise =
          [[FBLPromise wrapObjectCompletion:^(FBLPromiseObjectCompletion handler) {
            [[[[[[FIRDatabase database] reference] child:USERS_TABLE]
                queryOrderedByChild:@"user_id"]
                    queryEqualToValue:[[obj objectForKey:@"data"] objectForKey:@"user_id"]]
                        observeSingleEventOfType:FIRDataEventTypeValue
                                       withBlock:handler];
          }] then:^id(FIRDataSnapshot *snapshot) {
            return snapshot.value.allObjects.firstObject;   
          }];
      FBLPromise<NSDictionary *> *skillFoundPromise =
          [[FBLPromise wrapObjectCompletion:^(FBLPromiseObjectCompletion handler) {
            [[[[[[FIRDatabase database] reference] child:SOME_TABLE]
                queryOrderedByChild:@"id"]
                    queryEqualToValue:[[obj objectForKey:@"data"] objectForKey:@"skill_id"]]
                        observeSingleEventOfType:FIRDataEventTypeValue
                                       withBlock:handler];
          }] then:^id(FIRDataSnapshot *snapshot) {
            return snapshot.value.allObjects.firstObject;   
          }];
      FNLPromise *modelPromise =
          [[FBLPromise all:@[userDataPromise, skillFoundPromise]] then:^id(NSArray *values) {
            NSDictionary *userData = values.firstObject;
            NSDictionary *skillFound = values.lastObject;
            return [[Model alloc] initWithUserData:userData skillFound:skillFound];
          }];
      [modelPromises addObject:modelPromise];
    }
  }
  return [FBLPromise all:modelPromises];
}] then:^id(NSArray<Model *> *models) {
  [MBProgressHUD hideHUDForView:self.view animated:YES];
  [self do_some_ui_stuff]; 
  return nil;
}];

Which can be simplified and refactored further, if you move some of the patterns into separate methods, for example.

chiragpurohit71085 commented 5 years ago

Thanks. I"ll try this

On Thu 25 Oct, 2018, 7:50 AM Anthony Shoumikhin, notifications@github.com wrote:

Hi @chiragpurohit71085 https://github.com/chiragpurohit71085,

I doubt that you really need to use FBLPromiseAwait at all. Normally, you should be good by simply chaining promises into pipelines, possibly with the help of misc extensions https://github.com/google/promises/blob/master/g3doc/index.md#extensions operators.

Like for your example I imagine something akin the following:

[[[self getSomeData] then:^id(NSDictionary notifications) { NSMutableArray<FBLPromise > modelPromises = [NSMutableArray new]; for(id key in notifications) { NSDictionary notification = notifications[key]; NSString *notificationType = notification[@"data"][@"type"];

if ([notificationType isEqualToString:@"SOMEREFERENCE"] ||
    [notificationType isEqualToString:@"conversation/deleteByInitiatingUser"]) {
  FBLPromise<NSDictionary *> *userDataPromise =
      [[FBLPromise wrapObjectCompletion:^(FBLPromiseObjectCompletion handler) {
        [[[[[[FIRDatabase database] reference] child:USERS_TABLE]
            queryOrderedByChild:@"user_id"]
                queryEqualToValue:[[obj objectForKey:@"data"] objectForKey:@"user_id"]]
                    observeSingleEventOfType:FIRDataEventTypeValue
                                   withBlock:handler];
      }] then:^id(FIRDataSnapshot *snapshot) {
        return snapshot.value.allObjects.firstObject;
      }];
  FBLPromise<NSDictionary *> *skillFoundPromise =
      [[FBLPromise wrapObjectCompletion:^(FBLPromiseObjectCompletion handler) {
        [[[[[[FIRDatabase database] reference] child:SOME_TABLE]
            queryOrderedByChild:@"id"]
                queryEqualToValue:[[obj objectForKey:@"data"] objectForKey:@"skill_id"]]
                    observeSingleEventOfType:FIRDataEventTypeValue
                                   withBlock:handler];
      }] then:^id(FIRDataSnapshot *snapshot) {
        return snapshot.value.allObjects.firstObject;
      }];
  FNLPromise *modelPromise =
      [[FBLPromise all:@[userDataPromise, skillFoundPromise]] then:^id(NSArray *values) {
        NSDictionary *userData = values.firstObject;
        NSDictionary *skillFound = values.lastObject;
        return [[Model alloc] initWithUserData:userData skillFound:skillFound];
      }];
  [modelPromises addObject:modelPromise];
}

} return [FBLPromise all:modelPromises]; }] then:^id(NSArray<Model > models) { [MBProgressHUD hideHUDForView:self.view animated:YES]; [self do_some_ui_stuff]; return nil; }];

Which can be simplified and refactored further, if you move some of the patterns into separate methods, for example.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/google/promises/issues/77#issuecomment-432890588, or mute the thread https://github.com/notifications/unsubscribe-auth/APH9ifpTZZ_hMrIpauWJJSRgW-79lP6Uks5uoSAIgaJpZM4X4aZV .