Условное исполнение - PullRequest
6 голосов
/ 17 марта 2019

Как условно пропустить обещание и ничего не делать.Я создал вложенное обещание, по которому у меня есть 7 .then.Но условно, мне нужно пропустить несколько .путем и ничего не делать в этом блоке, как этого добиться?

Мой полный код :

const admin = require('firebase-admin');
const rp = require('request-promise');

module.exports = function(req, res) {

const phone = String(req.body.phone).replace(/[^\d]/g, '');
const amount = parseInt(req.body.amount);
const couponCodeName = (req.body.couponCodeName);
const couponUsage = parseInt(req.body.couponUsage);
const usersCouponUsage = parseInt(req.body.usersCouponUsage);
const finalAddress = (req.body.finalAddress);
const planName = (req.body.planName);
const saveThisAddress = (req.body.saveThisAddress);
const orderNumber = (req.body.orderNumber);
const pay_id = (req.body.pay_id);

const options = {
    method: 'POST',
    uri:`https://..........`,
    body: {
        amount
    },
    json: true
};

return admin.auth().getUser(phone)
.then(userRecord => {

    return rp(options)
})
.then((orderResponse) => {
    return admin.database().ref('trs/'+ phone)
        .push({ pay_id: orderResponse.id })
    })
.then(() => {
    return admin.database().ref('ors/'+ phone)
        .push({ pay_id })
})
.then(() => { 
    return saveThisAddress === true ? 
        admin.database().ref('address/'+phone)
            .push({address: finalAddress}) : null
})
.then(() => {
    return admin.database().ref('deliveryStatus/'+phone+'/'+orderNumber)
        .set({ plan: planName === "" ? "Single Day Plan" : planName, delivered: false}, () => {
            res.status(200).send({ success:true })
        })
}) 
.then(() => {
    return couponCodeName === "" ? null : 
        admin.database().ref(`couponCodes/${couponCodeName}`)
            .update({couponUsage: couponUsage + 1 })
})
.then(() => {
    return usersCouponUsage === "" ? null : 
        admin.database().ref(`couponUsage/${phone}`)
            .update({ [couponCodeName]: usersCouponUsage + 1 })
})
.catch((err) => {
    res.status(422).send({ error: err })
})    
 .catch((err) => {
 res.status(422).send({error: err });
 });
 }

Из приведенного выше кода два последних .then имеет условие return couponCodeName === ""?null: код ...)}.

Что мне нужно сделать, так это, когда couponCodeName === "" тогда, он должен пропустить блок .then и ничего не делать.Но, я возвращаю ноль в этом, это бросает необработанную ошибку отклонения.Так как этого добиться?Как пропустить .then и ничего не делать (важно ничего не делать, просто пропустить это). Как это сделать?

ОШИБКА, КОТОРУЮ Я ПОЛУЧАЮ, ЭТО: Ошибка, которую я получаюиз этих вложенных .then - «Необработанный отказ» & «Ошибка: невозможно установить заголовки после их отправки.»

Ошибка функции Google Cloud

Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:369:11)
at ServerResponse.header (/var/tmp/worker/node_modules/express/lib/response.js:767:10)
at ServerResponse.send (/var/tmp/worker/node_modules/express/lib/response.js:170:12)
at ServerResponse.json (/var/tmp/worker/node_modules/express/lib/response.js:267:15)
at ServerResponse.send (/var/tmp/worker/node_modules/express/lib/response.js:158:21)
at admin.auth.getUser.then.then.then.then.then.then.then.catch.catch (/user_code/request_payment_details.js:86:28)
at process._tickDomainCallback (internal/process/next_tick.js:135:7)

А также

Unhandled rejection

Примечание: версия узла Js: 6 (так что я думаю, что официально, я не могу использовать async и ждать)

Ответы [ 4 ]

3 голосов
/ 17 марта 2019

Может быть, вы можете использовать async/await для этого, так как вам нужна синхронизация:

async function doSomething() {
    var res1 = await promise1();
    if (res1 === xxx) {
        var res2 = await promise2();
    } else {
        ...
    }
}
1 голос
/ 17 марта 2019

Часть 1. Ваш обработчик ошибок не должен падать.

Если вы позвоните res.status(200), Express начнет потоковую передачу данных клиенту (заголовки уже отправлены). После этого вы не можете изменить статус ответа с помощью res.status(500), поскольку код состояния уже находится на пути к клиенту.

 stuff()
 .then(result => {
   res.status(200).send(result); // server starts sending
 }).then(moreStuff) // error occurs here
 .catch(error => {
   res.status(500).send(error); // fails, as server is already sending
 });

Чтобы решить эту проблему, вы должны начинать потоковую передачу любых данных только после выполнения всех ваших задач:

 stuff().then(moreStuff).then(evenMoreStuff) // error occurs here
   .then(result => {
      res.status(200).send(result); // doesnt get executed
   }).catch(error => {
      console.error(error);
      res.status(500).send("Whoops, server error\n" + error.message); // works
   });

Часть 2. Логика внутри вашей ошибки не должна выдаваться вообще.

Теперь, когда обработчик ошибок работает правильно, вы сможете узнать, что на самом деле идет не так в вашем коде.

(Мы не можем помочь вам без правильного сообщения об ошибке)


Часть 3. Реализация требуемого условного выполнения:

Чтобы условно выполнить обещания, вы должны вложить их:

 a().then(() => {
  if(!stuff) return; // exit early, continue at next then

  return b().then(c); // conditionally execute b and c
 }).then(rest); // executes after b and c if stuff is true

Часть 4. Теперь, когда все работает, вы можете изменить код на async / await, чтобы сделать его более читабельным:

Как вы указали, v6 dpes не поддерживает async / await, вам придется перейти на v8 или вы перенесете его с помощью веб-пакета :

module.exports = async function(req, res) {
  try {
     //...
     const userRecord = await admin.auth().getUser(phone);
     const orderResponse = await rp(options)

     await admin.database().ref('trs/'+ phone)
      .push({ pay_id: orderResponse.id });

     await admin.database().ref('ors/'+ phone)
      .push({ pay_id })

     if(saveThisAddress === true) {
       await admin.database().ref('address/'+phone)
        .push({address: finalAddress});
     }

     await admin.database().ref('deliveryStatus/'+phone+'/'+orderNumber)
      .set({ plan: planName === "" ? "Single Day Plan" : planName, delivered: false});

     if(couponCodeName !== "") {       
       await admin.database().ref(`couponCodes/${couponCodeName}`)
        .update({couponUsage: couponUsage + 1 });
     }

     if(usersCouponUsage !== "") {
       await admin.database().ref(`couponUsage/${phone}`)
        .update({ [couponCodeName]: usersCouponUsage + 1 });
     }

     res.status(200).send({ success:true });
  } catch(error) {
    console.error("Error inside API", error);
    res.status(422).send({ error });
  }
};
0 голосов
/ 17 марта 2019

Скажите, если хотите игнорировать этот блок:

.then(() => {
    return admin.database().ref('deliveryStatus/'+phone+'/'+orderNumber)
        .set({ plan: planName === "" ? "Single Day Plan" : planName, delivered: false}, () => {
            res.status(200).send({ success:true })
        })
}) 

Вы просто возвращаете решенное обещание перейти к следующему следующему, например, так:

.then(() => {
    if (<some-conditions>) {
       return Promise.resolve(<optional-data>);   
    } else {    // If directly want to go to first catch statement following
       return Promise.reject(<optional-data>)
    }

    return admin.database().ref('deliveryStatus/'+phone+'/'+orderNumber)
        .set({ plan: planName === "" ? "Single Day Plan" : planName, delivered: false}, () => {
            res.status(200).send({ success:true })
        })
}) 

В вашем случае игнорироватьэтот блок кода:

.then(() => {
    return couponCodeName === "" ? null : 
        admin.database().ref(`couponCodes/${couponCodeName}`)
            .update({couponUsage: couponUsage + 1 })
})

Поместите это так:

.then(() => {
    return couponCodeName ? Promise.resolve() :      // "" and null evaluates to false
        admin.database().ref(`couponCodes/${couponCodeName}`)
            .update({couponUsage: couponUsage + 1 })
})

enter image description here

Счастливое кодирование 101

0 голосов
/ 17 марта 2019

Как насчет

.then(() => {
            return couponCodeName === "" ? null : 
                admin.database().ref(`couponCodes/${couponCodeName}`)
                    .update({couponUsage: couponUsage + 1 })
                .then(() => {
                            admin.database().ref(`couponUsage/${phone}`)
                                .update({ [couponCodeName]: usersCouponUsage + 1 })
                            })}

...