【问题标题】:How to properly use resolve and reject for promises如何正确使用resolve和reject作为promise
【发布时间】:2018-01-16 15:16:48
【问题描述】:

我已经开始研究如何使用 Promises,并首先将一个简单的函数放在一起并调用了几次。我需要对拒绝和解决进行全面检查。

  1. 这是“承诺”函数的正确方法吗?
  2. 这是处理拒绝和解决的正确方法吗?
  3. 我有什么完全错误的吗?

    const Redis     = require('ioredis');
    const redis     = new Redis({
        port: 6379,
        host: '127.0.0.1'
    });
    
    
    function checkValues(name, section) {
        return new Promise((resolve, reject) => {
            redis.multi()
            .sismember('names', name)
            .sismember('sections', section)
            .exec()
            .then((results) => {
                if(results[0][1] === 1 && results [1][1] ===1) {
                    reject('Match on both.');
                } else if(results[0][1] === 1 || results [1][1] ===1) {
                    reject('Match on one.');
                } else {
                    redis.multi()
                    .sadd('names', name)
                    .sadd('sections', section)
                    .exec()
                    .then((results) => {
                        // Lazy assumption of success.
                        resolve('Added as no matches.');
                    })
                    // No catch needed as this would be thrown up and caught?
                }
            })
            .catch((error) => {
                console.log(error);
            });
        });
    }
    
    
    // Call stuff.
    checkValues('barry', 'green')
    .then((result) => {
        // Added as no matches "resolve" message from 'barry', 'green'
        console.log(result); 
        retutn checkValues('steve', 'blue');
    })
    .then((result) => {
        // Added as no matches "resolve" message from 'steve', 'blue'
        retutn checkValues('steve', 'blue');
    })
    .then((result) => {
        // Match on both "reject" message from 'steve', 'blue'
        console.log(result);
    })
    .catch((error) => {
        console.log(error);
    });
    

【问题讨论】:

    标签: javascript node.js promise


    【解决方案1】:

    不,这是一种反模式。您已经有一个返回 Promise 的函数,因此您不需要将它包装在另一个 Promise 中,您只需返回它即可。请记住,then() 返回一个解析为返回值then 的承诺。您还可以从then 返回另一个承诺。通常这看起来非常干净,但在这种情况下,您需要在 then 函数中添加一些逻辑,所以它会变得有点混乱。

    function checkValues(name, section) {
      // Just return this Promise
      return redis.multi()
        .sismember('names', name)
        .sismember('sections', section)
        .exec()
        .then((results) => {
            if(results[0][1] === 1 && results [1][1] ===1) {
                // Rejections will be caught down the line
                return Promise.reject('Match on both.');
            } else if(results[0][1] === 1 || results [1][1] ===1) {
                return Promise.reject('Match on one.');
            } else {
                // You can return another Promise from then()
                return redis.multi()
                .sadd('names', name)
                .sadd('sections', section)
                .exec()
            }
        })
     // You don't need to catch here - you can catch everything at the end of the chain
    }
    

    【讨论】:

      【解决方案2】:

      几点:

      1. 不要使用explicit-promise-construction-antipattern
      2. 作为清除反模式的一般指南,删除 new Promise() 包装后,将 resolve 语句更改为 returnreject 语句更改为 throw new Error(...)
      3. .catch() 抓住了!如果调用者可以观察/处理错误,那么要么不要在checkValues() 中捕获,要么捕获并重新抛出。捕获而不重新抛出将导致返回的 Promise 稳定在它的成功路径上,而不是它的错误路径上,这对于错误恢复非常有用,但并不总是合适的。
      4. 建议所有三种情况,“同时匹配”、“匹配一个”和“添加为未匹配”,都是真正的成功。除非有特殊原因需要将“同时匹配”和“同时匹配”视为错误条件,否则 return 而不是 reject/throw。这样一来,无论预期结果如何,您的 call stuff 链都会沿着其成功路径 .then().then().then() 前进;只有意外的错误才会沿着错误路径被最终的.catch() 捕获。这不是一般规则。很多时候,投掷是正确的做法,但不是在这里。
      function checkValues(name, section) {
          return redis.multi()
          .sismember('names', name)
          .sismember('sections', section)
          .exec()
          .then((results) => {
              if(results[0][1] === 1 && results [1][1] === 1) {
                  return 'Match on both.';
              } else if(results[0][1] === 1 || results [1][1] ===1) {
                  return 'Match on one.';
              } else {
                  return redis.multi()
                  .sadd('names', name)
                  .sadd('sections', section)
                  .exec()
                  .then((results) => {
                      return 'Added as no matches.';
                  });
              }
          })
          .catch((error) => {
              console.log(error);
              throw error;
          });
      }
      
      // Call stuff.
      checkValues('barry', 'green')
      .then((result) => {
          console.log(result); // expect 'Added as no matches'
          return checkValues('steve', 'blue');
      })
      .then((result) => {
          return checkValues('steve', 'blue'); // expect 'Added as no matches'
      })
      .then((result) => {
          console.log(result); // expect 'Match on both'
      })
      .catch((error) => {
          // only an unexpected error will land here
          console.log(error);
      });
      

      【讨论】:

      • 感谢您的详细回复。当我返回时,我可以返回多个值,例如:{success: 'false', message: 'single match'}。还是有更好/标准的方法来解决这个问题?
      • 是的,这正是返回多个值的方式。事实上,这是唯一的方法。 (好吧,你也可以返回一个构造对象,而不是一个普通对象,但这本质上是一样的)。
      猜你喜欢
      • 2019-01-20
      • 2019-04-07
      • 2018-10-10
      • 2015-11-15
      • 1970-01-01
      • 2019-09-15
      • 1970-01-01
      • 2017-11-09
      • 1970-01-01
      相关资源
      最近更新 更多