You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firebase Cloud Functions通知功能:修复Promise嵌套与错误返回问题

Fix Promise Nesting & Return Value Issues in Firebase Cloud Functions Notifications

Problem Overview

You're hitting two ESLint rule violations in your Firebase Cloud Functions notification code: promise nesting and missing return values in promise chains. These are causing your predeploy lint check to fail, and they also make your code harder to debug and maintain. Let's break down how to fix this.

First, here's your original code (with a small typo fixed for notification_id):

const functions = require('firebase-functions'); 
const admin= require('firebase-admin'); 
admin.initializeApp(); 
let firebaseConfig = JSON.parse(process.env.FIREBASE_CONFIG); 

exports.sendNotification = functions.database.ref('/Notifications/{user_id}/{notification_id}').onWrite((change,context) => { 
  const user_id = context.params.user_id; 
  const notification_id = context.params.notification_id; // Fixed typo
  console.log('We have a notification to send to ',user_id); 

  if(!change.after.val()){ 
    return console.log('A Notification has been deleted from the database : ', notification_id); 
  } 

  const deviceToken = admin.database().ref(`/Users/${user_id}/device_token`).once('value'); 
  return deviceToken.then(result =>{ 
    const token_id = result.val(); 
    const payload = { 
      notification: { 
        title : "Friend Request", 
        body : "You have received a new Friend Request", 
        icon : "default" 
      } 
    }; 
    return admin.messaging().sendToDevice(token_id, payload).then(response =>{ 
      console.log("This was the notification Feature"); 
    }); 
  });
});

And your ESLint/deployment errors:

31:21 warning Avoid nesting promises promise/no-nesting 
31:76 error Each then() should return a value or throw promise/always-return 
✖ 2 problems (1 error, 1 warning) 

npm ERR! code ELIFECYCLE 
npm ERR! errno 1 
npm ERR! functions@ lint: `eslint .` 
npm ERR! Exit status 1 
npm ERR! 
npm ERR! Failed at the functions@ lint script. 
npm ERR! This is probably not a problem with npm. There is likely additional logging output above. 
npm ERR! A complete log of this run can be found in: 
npm ERR! C:\Users\furkan\AppData\Roaming\npm-cache\_logs\2018-05-27T20_21_53_984Z-debug.log 

Error: functions predeploy error: Command terminated with non-zero exit code 1

Solution: Refactor for Flat Promise Chains & Proper Returns

I'll show you two approaches: one using async/await (cleaner, modern syntax) and one using flat promise chains (if you prefer sticking with .then()).

Option 1: Async/Await (Recommended)

This eliminates promise nesting entirely and makes error handling straightforward with try/catch:

const functions = require('firebase-functions'); 
const admin = require('firebase-admin'); 
admin.initializeApp(); 
// Note: You probably don't need to parse FIREBASE_CONFIG unless you use it elsewhere
// let firebaseConfig = JSON.parse(process.env.FIREBASE_CONFIG); 

exports.sendNotification = functions.database.ref('/Notifications/{user_id}/{notification_id}')
.onWrite(async (change, context) => { 
  const user_id = context.params.user_id; 
  const notification_id = context.params.notification_id; 
  console.log('We have a notification to send to ', user_id); 

  // Handle notification deletion: return a resolved promise (don't just return console.log)
  if (!change.after.val()) { 
    console.log('A Notification has been deleted from the database: ', notification_id); 
    return Promise.resolve(); 
  } 

  try {
    // Fetch the user's device token
    const tokenSnapshot = await admin.database().ref(`/Users/${user_id}/device_token`).once('value');
    const token_id = tokenSnapshot.val();

    // Exit early if no token exists
    if (!token_id) {
      console.log('No device token found for user: ', user_id);
      return Promise.resolve();
    }

    // Build notification payload
    const payload = { 
      notification: { 
        title: "Friend Request", 
        body: "You have received a new Friend Request", 
        icon: "default" 
      } 
    }; 

    // Send notification and return the result to signal completion
    const response = await admin.messaging().sendToDevice(token_id, payload);
    console.log("Notification sent successfully:", response);
    return response;
  } catch (error) {
    // Log and re-throw errors so Firebase tracks them
    console.error("Error sending notification:", error);
    throw error;
  }
});

Option 2: Flat Promise Chains

If you prefer to use .then() instead of async/await, we can flatten the chain and ensure every .then() returns a value:

const functions = require('firebase-functions'); 
const admin = require('firebase-admin'); 
admin.initializeApp(); 

exports.sendNotification = functions.database.ref('/Notifications/{user_id}/{notification_id}')
.onWrite((change, context) => { 
  const user_id = context.params.user_id; 
  const notification_id = context.params.notification_id; 
  console.log('We have a notification to send to ', user_id); 

  if (!change.after.val()) { 
    console.log('A Notification has been deleted from the database: ', notification_id); 
    return Promise.resolve(); 
  } 

  // Flat chain instead of nesting .then() calls
  return admin.database().ref(`/Users/${user_id}/device_token`).once('value')
    .then(tokenSnapshot => {
      const token_id = tokenSnapshot.val();
      if (!token_id) {
        console.log('No device token found for user: ', user_id);
        return Promise.resolve();
      }
      const payload = { 
        notification: { 
          title: "Friend Request", 
          body: "You have received a new Friend Request", 
          icon: "default" 
        } 
      }; 
      // Return the sendToDevice promise to continue the chain
      return admin.messaging().sendToDevice(token_id, payload);
    })
    .then(response => {
      console.log("Notification sent successfully:", response);
      return response; // Return value to satisfy ESLint's always-return rule
    })
    .catch(error => {
      console.error("Error sending notification:", error);
      throw error; // Propagate error to Firebase
    });
});

Key Fixes Explained:

  1. Eliminated Promise Nesting: In the original code, you nested a .then() inside another .then()—we fixed this by chaining promises instead, resolving the promise/no-nesting warning.
  2. Proper Return Values:
    • For the deletion case, we return Promise.resolve() instead of just console.log (Cloud Functions require a promise return to signal completion).
    • Every .then() (or await call) returns a value or promise, fixing the promise/always-return error.
  3. Added Error Handling: We added try/catch (for async/await) or .catch() (for chains) to log and propagate errors, so Firebase can track failures properly.
  4. Token Check: We now handle the case where a user doesn't have a device token stored, avoiding unnecessary API calls.
  5. Fixed Typo: Corrected the variable name from notification to notification_id in the deletion log.

内容的提问来源于stack exchange,提问作者f.knyr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:33:07