How to avoid nested promises?

ぃ、小莉子 提交于 2019-12-11 21:25:28

问题


I'm trying to write firebase function and I wonder if is any way to avoid nested promises in this JavaScript code?

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;
        });

    });
});
});

Does somebody any idea how can I avoid nested promises in this code?


回答1:


Move the nested then calls to the outer promise chain, and pass the variables you need in a next then callback as extra value in the Promise.all call:

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:


In ES7, you can wrap the entire code around an async function and use await:

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

f();

You will need to be on Node version >= 7 or use Babel.



来源:https://stackoverflow.com/questions/50318627/how-to-avoid-nested-promises

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!