Как разрешить разные обещания в каждом случае блока переключателей и передать их результаты одной и той же функции? - PullRequest
0 голосов
/ 21 января 2019

Предположим, что я хочу выполнить разные цепочки обещаний в различных блоках case блока switch и в конечном итоге вернуть результат клиенту через res.end(), например:

app.post('/endpoint',function(req,res){
    var reqValue=req.body.value;
    var resValue="initial value";
    switch(reqValue){
         case 'a':
             someObj.action_a()
             .then(result=>{
                 resValue=result.id;
             });
             break;
         case 'b':
             someObj.action_b()
             .then(result=>{
                 resValue=result.id;
             });
             break;
         default:
             resValue="default";
    }
    doSomethingElse();
    res.end(resValue);
});

В конечном итоге resValue возвращается как "initial value", что имеет смысл, поскольку асинхронные функции в блоках case не обновляют resValue до того, как выполнение достигнет res.end().Я мог бы переместить код post-switch в разрешения обещаний, например:

         case 'a':
             someObj.action_a()
             .then(result=>{
                 resValue=result.id;
                 doSomethingElse();
                 res.end(resValue);
             });
             break;
         case 'b':
             someObj.action_b()
             .then(result=>{
                 resValue=result.id;
                 doSomethingElse();
                 res.end(resValue);
             });
             break;
         default:
             resValue="default";
             doSomethingElse();
             res.end(resValue);

, но тогда это дублирующий код и, следовательно, более сложный в обслуживании.Есть ли лучший способ, чтобы эти switch опосредованные обещания все заканчивались в одном и том же res.end()?

Ответы [ 5 ]

0 голосов
/ 21 января 2019

Вот один вариант, если вы не можете использовать async/await и вместо этого должны придерживаться Promises (Однако вложенные троицы могут стать неприглядными, если у вас много случаев; читайте дальше для другой идеи):

app.post('/endpoint', function(req, res) {
  const reqValue = req.body.value;
  (reqValue === 'a'
    ? someObj.action_a().then(({id}) => id)
    : reqValue === 'b'
      ? someObj.action_b.then(({id}) => id)
      : Promise.resolve('default'))
        .then(resValue => {
          doSomethingElse();
          res.end(resValue);
        });
});

Вместо этого предположим, что вы сохраняете свои действия в Object:

const actions = {
  a: () => someObj.action_a();
  b: () => someObj.action_b();
  // ...
  n: () => someObj.action_n();
};

app.post('endpoint', function(req, res) {
  const action = actions[req.body.value];
  (action && action().then(({id}) => id) || Promise.resolve('default'))
    .then(resValue => {
      doSomethingElse();
      res.end(resValue);
    });
});
0 голосов
/ 21 января 2019

Возможно, вместо этого вы могли бы создать общую функцию, которая будет возвращать данные в зависимости от заданного типа действия, и иметь там switch, и использовать простую асинхронность / ожидание в вашей главной функции просто для ожидания результата, который

// Made up function that switches action
// based on the type (in this case the timer on the
// setTimeout)
function doAction(type) {
  let time;
  switch(type) {
    case 'a': time = 1000; break;
    case 'b': time = 2000; break;
    case 'c': time = 300; break;
  }
  return new Promise(resolve => {
    setTimeout(() => resolve({ id: `${type}1` }), time);
  });
}

async function main(type) {
  try {

    // Pass in the type to the doAction function,
    // let that decide what to do, and await the promise
    // to resolve
    const result = await doAction(type);

    // Then just console.log or res.send the result 
    const resValue = result.id;
    console.log(resValue);
  } catch (e) {
    console.log(e);
  }
}

main('b');
main('a');
main('c');
0 голосов
/ 21 января 2019

Promise.all - очень удобный инструмент для отслеживания всех заданий под-обещаний

const jobqQeue = [];

switch(...) {
  case: '...': {
    jobqQeue.push(
      subPromise()
    );
  }
  case: '...': {
    jobqQeue.push(
      subPromise2()
    );
  }
  default: {
    jobqQeue.push(
      defaultOpPromise();
    );
  }
}

Promise.all(jobqQeue)
.then(results => {
  ...
})
.catch(error => console.error(error));
0 голосов
/ 21 января 2019

Если вы можете использовать новые функции JavaScript, я бы порекомендовал async и await, потому что они просты для чтения и использования, ваш код изменится на:

let resValue = "default";
switch (reqValue) {
  case 'a':
    resValue = (await someObj.action_a()).id;
    break;
  case 'b':
    resValue = (await someObj.action_b()).id;
    break;
  default:
    break;
}
doSomethingElse();
res.end(resValue);
0 голосов
/ 21 января 2019

Вы можете использовать одну переменную для хранения обещания требуемого resValue, например,

app.post('/endpoint',function(req,res){
    let reqValue=req.body.value;
    let p;
    switch(reqValue){
         case 'a':
             p = someObj.action_a().then(result => result.id);
             break;
         case 'b':
             p = someObj.action_b().then(result => result.id);
             break;
         default:
             // p has to be a promise, so make it one
             p = Promise.resolve("default");
    }
    p.then(resValue => {
        doSomethingElse();
        res.end(resValue);
    });
});

или используя современный JavaScript, используйте async / await

app.post('/endpoint',async function(req,res){
    let reqValue=req.body.value;
    let resValue="initial value";
    switch(reqValue){
         case 'a':
             resValue = await someObj.action_a().then(result => result.id);
             break;
         case 'b':
             resValue = await someObj.action_b().then(result => result.id);
             break;
         default:
             resValue = "default";
    }
    doSomethingElse();
    res.end(resValue);
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...