我已经开始考虑使用Promise,并且已经开始通过组合一个简单的函数并调用它几次。我需要在拒绝和解决方面进行健全检查。
我完全错了什么?
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);
});
答案 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)
有几点:
new Promise()
包装后,将resolve
语句更改为return
和reject
语句为throw new Error(...)
.catch()
抓住了!如果调用者可以观察到/可以处理错误,那么要么不要进入checkValues()
,要么抓住并重新投掷。在不重新投掷的情况下捕获将导致返回的承诺在其成功路径上得到解决,而不是错误路径,这对于错误恢复非常有用,但并不总是合适。return
而不是reject
/ throw
。这样,无论预期结果如何,您的调用内容链都将沿着其成功路径.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);
});