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

如何解决每种情况下开关块的不同承诺,并将其结果传递给相同的功能?

  •  0
  • sigil  · 技术社区  · 6 年前

    假设我想执行不同的承诺链 case A块 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 '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);
    

    但这是复制代码,因此维护起来更具挑战性。有更好的方法吗 转换 -调解的承诺最终都是一样的。 结束() ?

    5 回复  |  直到 6 年前
        1
  •  2
  •   Jaromanda X    6 年前

    您可以使用一个变量来保持所需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);
    });
    
        2
  •  3
  •   vdegenne Kuba Å imonovský    6 年前

    如果你能使用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);
    
        3
  •  0
  •   Andy    6 年前

    相反,您可以创建一个通用函数,该函数根据给定的操作类型返回数据,并具有 switch 然后在主函数中使用一个简单的async/await来等待

    // 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');
        4
  •  0
  •   Scott Rudiger    6 年前

    如果你不能使用,这里有一个选项 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);
        });
    });
    
        5
  •  -1
  •   Felix Fong    6 年前

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