@@ -39,6 +39,7 @@ import {
3939 MessagingConditionResponse ,
4040 DataMessagePayload ,
4141 NotificationMessagePayload ,
42+ SendResponse ,
4243} from './messaging-api' ;
4344
4445// FCM endpoints
@@ -250,17 +251,16 @@ export class Messaging {
250251 } ) ;
251252 }
252253
253- // TODO: Update the comment based on the implementation
254254 /**
255255 * Sends each message in the given array via Firebase Cloud Messaging.
256256 *
257- * Unlike {@link Messaging.sendAll}, this method makes a single RPC call for each message in the given array.
257+ * Unlike {@link Messaging.sendAll}, this method makes a single RPC call for each message
258+ * in the given array.
258259 *
259- * The responses list obtained from the return value
260- * corresponds to the order of `messages`. An error
261- * from this method indicates a total failure -- i.e. none of the messages in
262- * the list could be sent. Partial failures are indicated by a `BatchResponse`
263- * return value.
260+ * The responses list obtained from the return value corresponds to the order of `messages`.
261+ * An error from this method or a `BatchResponse` with all failures indicates a total failure
262+ * -- i.e. none of the messages in the list could be sent. Partial failures or no failures
263+ * are only indicated by a `BatchResponse` return value.
264264 *
265265 * @param messages - A non-empty array
266266 * containing up to 500 messages.
@@ -270,22 +270,67 @@ export class Messaging {
270270 * send operation.
271271 */
272272 public sendEach ( messages : Message [ ] , dryRun ?: boolean ) : Promise < BatchResponse > {
273- //TODO: add implementation
274- console . log ( messages , dryRun ) ;
275- return Promise . resolve ( { responses : [ ] , successCount : 0 , failureCount : 0 } ) ;
273+ if ( validator . isArray ( messages ) && messages . constructor !== Array ) {
274+ // In more recent JS specs, an array-like object might have a constructor that is not of
275+ // Array type. Our deepCopy() method doesn't handle them properly. Convert such objects to
276+ // a regular array here before calling deepCopy(). See issue #566 for details.
277+ messages = Array . from ( messages ) ;
278+ }
279+
280+ const copy : Message [ ] = deepCopy ( messages ) ;
281+ if ( ! validator . isNonEmptyArray ( copy ) ) {
282+ throw new FirebaseMessagingError (
283+ MessagingClientErrorCode . INVALID_ARGUMENT , 'messages must be a non-empty array' ) ;
284+ }
285+ if ( copy . length > FCM_MAX_BATCH_SIZE ) {
286+ throw new FirebaseMessagingError (
287+ MessagingClientErrorCode . INVALID_ARGUMENT ,
288+ `messages list must not contain more than ${ FCM_MAX_BATCH_SIZE } items` ) ;
289+ }
290+ if ( typeof dryRun !== 'undefined' && ! validator . isBoolean ( dryRun ) ) {
291+ throw new FirebaseMessagingError (
292+ MessagingClientErrorCode . INVALID_ARGUMENT , 'dryRun must be a boolean' ) ;
293+ }
294+
295+ return this . getUrlPath ( )
296+ . then ( ( urlPath ) => {
297+ const requests : Promise < SendResponse > [ ] = copy . map ( ( message ) => {
298+ validateMessage ( message ) ;
299+ const request : { message : Message ; validate_only ?: boolean } = { message } ;
300+ if ( dryRun ) {
301+ request . validate_only = true ;
302+ }
303+ return this . messagingRequestHandler . invokeRequestHandlerForSendResponse ( FCM_SEND_HOST , urlPath , request ) ;
304+ } ) ;
305+ return Promise . allSettled ( requests ) ;
306+ } ) . then ( ( results ) => {
307+ const responses : SendResponse [ ] = [ ] ;
308+ results . forEach ( result => {
309+ if ( result . status === 'fulfilled' ) {
310+ responses . push ( result . value ) ;
311+ } else { // rejected
312+ responses . push ( { success : false , error : result . reason } )
313+ }
314+ } )
315+ const successCount : number = responses . filter ( ( resp ) => resp . success ) . length ;
316+ return {
317+ responses,
318+ successCount,
319+ failureCount : responses . length - successCount ,
320+ } ;
321+ } ) ;
276322 }
277323
278- // TODO: Update the comment based on the implementation
279324 /**
280325 * Sends the given multicast message to all the FCM registration tokens
281326 * specified in it.
282327 *
283328 * This method uses the {@link Messaging.sendEach} API under the hood to send the given
284329 * message to all the target recipients. The responses list obtained from the
285330 * return value corresponds to the order of tokens in the `MulticastMessage`.
286- * An error from this method indicates a total failure -- i.e. the message was
287- * not sent to any of the tokens in the list. Partial failures are indicated by
288- * a `BatchResponse` return value.
331+ * An error from this method or a `BatchResponse` with all failures indicates a total failure
332+ * -- i.e. none of the messages in the list could be sent . Partial failures or no failures
333+ * are only indicated by a `BatchResponse` return value.
289334 *
290335 * @param message - A multicast message
291336 * containing up to 500 tokens.
@@ -295,9 +340,33 @@ export class Messaging {
295340 * send operation.
296341 */
297342 public sendEachForMulticast ( message : MulticastMessage , dryRun ?: boolean ) : Promise < BatchResponse > {
298- //TODO: add implementation
299- console . log ( message , dryRun ) ;
300- return Promise . resolve ( { responses : [ ] , successCount : 0 , failureCount : 0 } ) ;
343+ const copy : MulticastMessage = deepCopy ( message ) ;
344+ if ( ! validator . isNonNullObject ( copy ) ) {
345+ throw new FirebaseMessagingError (
346+ MessagingClientErrorCode . INVALID_ARGUMENT , 'MulticastMessage must be a non-null object' ) ;
347+ }
348+ if ( ! validator . isNonEmptyArray ( copy . tokens ) ) {
349+ throw new FirebaseMessagingError (
350+ MessagingClientErrorCode . INVALID_ARGUMENT , 'tokens must be a non-empty array' ) ;
351+ }
352+ if ( copy . tokens . length > FCM_MAX_BATCH_SIZE ) {
353+ throw new FirebaseMessagingError (
354+ MessagingClientErrorCode . INVALID_ARGUMENT ,
355+ `tokens list must not contain more than ${ FCM_MAX_BATCH_SIZE } items` ) ;
356+ }
357+
358+ const messages : Message [ ] = copy . tokens . map ( ( token ) => {
359+ return {
360+ token,
361+ android : copy . android ,
362+ apns : copy . apns ,
363+ data : copy . data ,
364+ notification : copy . notification ,
365+ webpush : copy . webpush ,
366+ fcmOptions : copy . fcmOptions ,
367+ } ;
368+ } ) ;
369+ return this . sendEach ( messages , dryRun ) ;
301370 }
302371
303372 /**
0 commit comments