我研究过几个相关问题&答案,仍然无法找到我正在尝试做的解决方案。我正在使用Mongoose和Bluebird作承诺。
我的承诺链包含3个部分:
按用户名
如果找到了用户1,请按用户名
如果找到了用户1和用户2,则存储新记录
如果步骤1或步骤2无法返回用户,我不想执行步骤3.但是,如果未能返回用户,则不会导致数据库错误,因此我需要检查有效用户手动。
我可以在步骤1中使用type
TDatabaseRecord = class
public
ID: Integer;
Name: String;
end;
function FindNameByID(ID: Integer): String;
var
I: Integer;
begin
Result := '';
for I := 0 to MyList.Count-1 do
begin
if TDatabaseRecord(MyList[I]).ID = ID then
begin
Result := TDatabaseRecord(MyList[I]).Name;
Exit;
end;
end;
end;
,它将跳过第2步,但仍会执行第3步。其他答案建议使用Promise.reject()
,但我似乎也无法做到这一点。
我的代码如下。 (我的函数cancel()
返回一个承诺。)
User.findByName()
答案 0 :(得分:2)
你需要做的就是这样:
let findUserOrFail = name =>
User.findByName(name).then(v => v || Promise.reject('not found'));
Promise.all(['robfake', 'bobbyfake'].map(findUserOrFail)).then(users => {
var record = new LedgerRecord({
transactionDate: Date.now(),
fromUser: users[0],
toUser: users[1],
});
return record.save();
}).then(result => {
// result of successful save
}).catch(err => {
// handle errors - both for users and for save
});
您可以创建一个功能:
let findUserOrFail = name =>
User.findByName(name).then(v => v || Promise.reject('not found'));
然后你可以按照自己的意愿使用它。
E.g。你可以这样做:
Promise.all([user1, user1].map(findUserOrFail)).then(users => {
// you have both users
}).catch(err => {
// you don't have both users
});
这种方式会更快,因为您不必等待第一个用户获得第二个用户 - 两者都可以并行查询 - 并且您可以在以后将其扩展到更多用户:
let array = ['array', 'with', '20', 'users'];
Promise.all(array.map(findUserOrFail)).then(users => {
// you have all users
}).catch(err => {
// you don't have all users
});
无需复杂化。
答案 1 :(得分:0)
将错误处理从内链移到您想要实际捕获/处理它的位置。由于我没有安装mongo,这里有一些伪代码可以解决这个问题:
function findUser1(){
return Promise.resolve({
user: 1
});
}
function findUser2(){
return Promise.resolve({
user: 2
});
}
function createRecord(user1, user2){
return Promise.resolve({
fromUser: user1,
toUser: user2,
});
}
findUser1()
.then(user1 => findUser2()
.then(user2 => createRecord(user1, user2))) // better nest your promises as having variables in your outside scope
.then(record => console.log('record created'))
.catch(err => console.log(err)); // error is passed to here, every then chain until here gets ignored
通过将findUser1更改为
来尝试return Promise.reject('not found 1');
答案 2 :(得分:0)
首先,我建议使用In [62]:
df.groupby('id').head(1)
Out[62]:
summary id
183 12.0 11
14 6.0 17
4 6.0 18
代替throw x;
,仅出于可读性原因。其次,您的错误记录功能会捕获所有错误,这就是您的承诺链继续存在的原因。尝试重新抛出错误:
return Promise.reject(x);
答案 3 :(得分:0)
不要将错误记录到任何地方而不实际处理错误 - 如果您传递错误处理程序回调,那么您将获得将履行undefined
的承诺,这不是你需要的。只需使用
User.findByName('robfake').then(fromUser => {
if (fromUser) {
return User.findByName('bobbyfake').then(toUser => {
if (toUser) {
var record = new LedgerRecord({
transactionDate: Date.now(),
fromUser,
toUser
});
return record.save()
} else {
console.log('user2 not found');
}
});
} else {
console.log('user1 not found');
}
}).then(doc => {
if (doc) {
console.log('saved', doc);
} else {
console.log('saved nothing')
}
}, err => {
console.error("something really bad happened somewhere in the chain", err);
});
这将始终记录其中一个"已保存的"或者"坏事"消息,可能还有一个"未找到"之前的消息。
你也可以使用例外来实现这一点,但它并没有变得更简单:
var user1 = User.findByName('robfake').then(fromUser => {
if (fromUser)
return fromUser;
else
throw new Error('user1 not found');
});
var user2 = user1.then(() => // omit this if you want them to be searched in parallel
User.findByName('bobbyfake').then(toUser => {
if (toUser)
return toUser;
else
throw new Error('user2 not found');
})
);
Promise.all([user1, user2]).then([fromUser, toUser]) =>
var record = new LedgerRecord({
transactionDate: Date.now(),
fromUser,
toUser
});
return record.save();
}).then(doc => {
if (doc) {
console.log('saved', doc);
} else {
console.log('saved nothing')
}
}, err => {
console.error(err.message);
});