代码之家  ›  专栏  ›  技术社区  ›  Andromeda

Firebase云函数已完成,状态为“错误”

  •  1
  • Andromeda  · 技术社区  · 6 年前

    我正在编写我的第一个云函数,以便在新用户注册我的android应用程序时发送推送通知。我已经完成了安装Node和firebase cli等基础工作,并初始化了项目。

    我在下面编写了这个测试函数,用于记录注册并部署到firebase的任何用户的用户id及其令牌。

     exports.sendSignUpNotification =functions.database.ref('/users/{userId}').onWrite((change, context) => {
    const user_id = context.params.userId;
    //const notifID = context.params.notification_id;
    console.log("User id at signup:\t", user_id);
    //console.log("Notification id at signup:\t", notifID);
    
    let token = admin.database().ref(`/users/{userId}/id_token`).once('value');
    console.log("User id token:\t", token);
    
     return new Promise().then(data => {
        const payLoad = {
        notification: {
           title: "Thank You For Signing Up",
           body: "Enjoy the best features by becoming a premium user"
         }
       };
       return admin.messaging().sendToDevice(token, payLoad);
     }).catch(errs => {
      console.error("Error Sending Payload", errs);
    });
    
    });
    

    这是完整功能的编辑代码,但不知何故,我知道我在发送有效负载时做错了什么。下面是我遇到的错误:

    TypeError: Promise resolver undefined is not a function
    at exports.sendSignUpNotification.functions.database.ref.onWrite (/user_code/index.js:15:10)
    at Object.<anonymous> (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:112:27)
    at next (native)
    at /user_code/node_modules/firebase-functions/lib/cloud-functions.js:28:71
    at __awaiter (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:24:12)
    at cloudFunction (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:82:36)
    at /var/tmp/worker/worker.js:716:24
    at process._tickDomainCallback (internal/process/next_tick.js:135:7)
    

    为了在客户端获取令牌,我在注册时调用了此方法:

    mAuth.getCurrentUser().getIdToken(true).addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
                                @Override
                                public void onComplete(@NonNull Task<GetTokenResult> task) {
                                    if (task.isSuccessful()) {
                                        String idToken = task.getResult().getToken();
                                        Log.d(TAG, "idToken:\t" + idToken);
    
                                        HashMap<String, String> usersMap = new HashMap<>();
                                        usersMap.put("name", name);
                                        usersMap.put("userId", userId);
                                        usersMap.put("email", email);
                                        usersMap.put("id_token", idToken);
              }
    

    我已经保存了这个令牌,并在我的云函数脚本中引用了它。这是正确的令牌还是我应该使用 FirebaseInstanceIdService 如下所示:

    @Override
    public void onTokenRefresh() {
        super.onTokenRefresh();
    
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
        Log.d(TAG, "Refreshed Token:\t" + refreshedToken);
    
    }
    

    非常感谢。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Doug Stevenson    6 年前

    您正在将旧的beta API与新的1一起使用。SDK的x版本。数据库事件的工作方式已经改变。总结了整个SDK的更改 here .onWrite事件现在接受两个参数,一个更改和一个上下文。更改包含前后快照,上下文包含通配符值。

    要获取用户ID通配符,您现在可以说:

    exports.sendSignUpNotification = functions.database.ref(`/users/{userId}`).onWrite((change, context) => {
        const userId = context.params.userId
    

    请参阅 documentation 更多当前示例。

    在您的代码中,这一行还有一个bug:

    let token = admin.database().ref(`/users/{userId}/notificationTokens`).once('value');
    

    反勾分隔字符串中变量插值的JavaScript语法需要美元符号:

    `/users/${userId}/notificationTokens`
    

    该行还有另一个bug。您没有使用once()返回的承诺来实际获取数据库中的值。 token 将包含该承诺,而不是数据库的内容。

    并且您还必须返回一个承诺,该承诺在函数中完成所有异步工作时得到解决,而您目前没有这样做。