如何正确使用解决方案并拒绝承诺

时间:2017-08-08 22:02:45

标签: javascript node.js promise

我已经开始考虑使用Promise,并且已经开始通过组合一个简单的函数并调用它几次。我需要在拒绝和解决方面进行健全检查。

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

2 个答案:

答案 0 :(得分:3)

不,这是一种反模式。你已经有了一个返回一个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
}

答案 1 :(得分:1)

有几点:

  1. 请勿使用explicit-promise-construction-antipattern
  2. 作为清除反模式的一般指南,在删除new Promise()包装后,将resolve语句更改为returnreject语句为throw new Error(...)
  3. .catch()抓住了!如果调用者可以观察到/可以处理错误,那么要么不要进入checkValues(),要么抓住并重新投掷。在不重新投掷的情况下捕获将导致返回的承诺在其成功路径上得到解决,而不是错误路径,这对于错误恢复非常有用,但并不总是合适。
  4. 建议所有这三种情况,“匹配”,“匹配一个”,“匹配一个'并且'添加为没有匹配',确实是成功的。除非有特别的理由想要在两者之间进行匹配。并且'匹配一个'被视为错误条件,然后是return而不是reject / throw。这样,无论预期结果如何,您的调用内容链都将沿着其成功路径.then().then().then()向下发展;只有意外错误才会在最终.catch()捕获错误路径。这不是一般规则;通常,投掷是正确的事情,但不是在这里。
  5. 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);
    });