繁体   English   中英

如何正确使用决心和拒绝诺言

[英]How to properly use resolve and reject for promises

我已经开始考虑使用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); }); 

不,这是一种反模式。 您已经有一个返回承诺的函数,因此您无需将其包装在另一个承诺中,只需将其返回即可。 请记住, 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. 不要使用显式的Promise-construction-antipattern
  2. 作为清除反模式的一般指南,请在删除new Promise()包装器后,将resolve语句更改为return然后将reject语句更改为throw new Error(...)
  3. .catch()抓住了! 如果调用者可以观察/处理错误,则不要捕获checkValues()或捕获并重新抛出。 捕获而不重新抛出将导致返回的承诺在其成功路径上建立,而不是在其错误路径上建立,这对错误恢复很有用,但并不总是合适的。
  4. 建议“同时匹配”,“同时匹配”和“添加为没有匹配”这三种情况都是成功的。 除非有特殊原因希望将“同时匹配”和“同时匹配”视为错误条件,否则请return而不是reject / throw 这样,您的呼叫物料链将沿着其成功路径.then().then().then()前进,而不管预期的结果如何; 只有意外的错误会沿着错误路径.catch() ,最终被.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);
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM