【问题标题】:How to avoid nested promises?如何避免嵌套承诺?
【发布时间】:2018-05-14 01:17:33
【问题描述】:

我正在尝试编写 firebase 函数,我想知道是否有任何方法可以避免此 JavaScript 代码中的嵌套承诺?

exports.sendNotification=functions.database.ref('/notifications/{user_id}/{notification_id}').onWrite((change,context)=>{

const userId=context.params.user_id;
const notificationId=context.params.notification_id;

console.log('We have a notification to send to: ', userId);

if(!change.after.val()){
    return console.log('A notification has been deleted from database ',notificationId);
}
const fromUser=change.after.ref.root.child("/notifications/"+userId+"/"+notificationId).once('value');
return fromUser.then(fromUserResult=>{
    const fromUserID=fromUserResult.val().from;
    console.log('You have new notification from'+fromUserID);

    const userQuery=change.after.ref.root.child(`users/${fromUserID}/name`).once('value');
    const deviceToken=change.after.ref.root.child("/users/"+userId+"/device_token").once('value');

    return Promise.all([userQuery, deviceToken]).then(resut=>{

        const userName=resut[0].val();
        const token_id=resut[1].val();

        const payload={
            notification:{
                title: "Friend request",
                body: `${userName} has send you request`,
                icon: "default",
                click_action: "com.mwdevp.android.lapitchat_TARGET_NOTIFICATION"
            },
            data :{
                USER_KEY: fromUserID
            }
        };

        return admin.messaging().sendToDevice(token_id,payload).then(response=>{
        console.log('This was the notification feature');
        return;
        });

    });
});
});

有人知道如何避免这段代码中的嵌套承诺吗?

【问题讨论】:

    标签: javascript promise nested


    【解决方案1】:

    将嵌套的then 调用移动到外部promise 链,并在下一个then 回调中将您需要的变量作为Promise.all 调用中的额外值传递:

    return fromUser.then(fromUserResult=>{
        const fromUserID=fromUserResult.val().from;
        console.log('You have new notification from'+fromUserID);
    
        const userQuery=change.after.ref.root.child(`users/${fromUserID}/name`).once('value');
        const deviceToken=change.after.ref.root.child("/users/"+userId+"/device_token").once('value');
    
        return Promise.all([userQuery, deviceToken, fromUserID]); // <--- add third value
    }).then(resut=>{
        const userName=resut[0].val();
        const token_id=resut[1].val();
    
        const payload={
            notification:{
                title: "Friend request",
                body: `${userName} has send you request`,
                icon: "default",
                click_action: "com.mwdevp.android.lapitchat_TARGET_NOTIFICATION"
            },
            data :{
                USER_KEY: resut[2]; // <----
            }
        };
    
        return admin.messaging().sendToDevice(token_id,payload);
    }).then(response=>{
        console.log('This was the notification feature');
        return;
    });
    

    【讨论】:

      【解决方案2】:

      在 ES7 中,您可以将整个代码包装在 async 函数周围并使用 await

      async function f() {
        ...
        const fromUserResult = await change.after.ref.root.child(...);
        ...
        const resut = await Promise.all(...);
        const userName = resut[0].val();
        ...
      }
      
      f();
      

      您需要使用 Node 版本 >= 7 或使用 Babel

      【讨论】:

        猜你喜欢
        • 2021-04-07
        • 2019-05-22
        • 2018-10-15
        • 2020-04-22
        相关资源
        最近更新 更多