私はまだ約束を完全に理解していないので、これが単純な誤解であるならば謝罪します。
ページ上のアイテムを削除する機能がありますが、ページの状態によって特定の動作があります。擬似コード的には、次のようになります。
Does the page have changes?
If yes - Prompt to save changes first
If yes - save changes
If no - exit function
If no - continue
Prompt to confirm delete
If yes - delete item and reload data
If no - exit function
うまくいけば、それは理にかなっています。基本的に、変更がある場合は、最初にデータを保存する必要があります。次に、データが保存されている場合、または最初から変更がない場合は、ユーザーに削除の確認を求めます。問題は、私がデュランダルとそよ風を使用していることであり、それらが正しく一緒に戻るという約束を連鎖させることができないようです。
私の関数は現在このように見えますが、これは間違っていることがわかっていますが、どこで修正するかを見つけるのに苦労しています。
if (this.hasChanges()) {
app.showMessage('Changes must be saved before removing external accounts. Would you like to save your changes now?', 'Unsaved Changes...', ['Yes', 'No'])
.then(function (selectedOption) {
if (selectedOption === 'Yes') {
return this.save();
} else {
Q.resolve()
}
});
}
app.showMessage('Are you sure you want to delete this item?', 'Delete?', ['Yes', 'No'])
.then(function (selectedOption) {
if (selectedOption === 'Yes') {
item.entityAspect.setDeleted();
datacontext.saveChanges()
.then(function () {
logger.logNotificationInfo('Item deleted.', '', router.activeInstruction().config.moduleId);
Q.resolve(this.refresh(true));
}.bind(this));
}
}.bind(this));
Durandalからのapp.showMessage呼び出しはpromiseを返し、次にthis.saveはpromiseを返し、最後にthis.refreshもpromiseを返します。
したがって、hasChangesを確認し、必要に応じてsaveを呼び出して、それを解決する必要があると思います。次に、その条件付きセクションの解決が完了した後、2番目のプロンプトを呼び出し、その中のすべてのプロミスを解決します。
申し訳ありませんが、これはあまり明確ではないと思いますが、それは私がここのチェーンを完全にフォローしていないという事実から来ていると思います。
どんな助けでも大歓迎です!ありがとう。
クリスは正しいです。 Q.resolve呼び出しは必要ありません。
ところで、解決された値true
またはfalse
でpromiseを返すことはあなたの状況では無意味です。 false
を返すと、連鎖したthen()
が呼び出されなくなるという誤った印象を受けているのではないかと思います。そうではありません!値がfalse
の解決済みのpromiseは、依然として適切なpromiseです...アラートメッセージボックスをトリガーする次のコードに示されています。
_Q(false) // same as Q.resolve(false)
.then(function () { alert('resolve(false) triggered then()') })
_
Promiseを失敗状態にしたい場合(そしてエラー値を気にしない場合)は、Q.reject()
を返す必要があります。
コードにthis
が含まれているのかわかりませんが、内部関数を実行するときに問題が発生するだけです。迷子になったり、bind(this)
ロジックの補正に苦労したりしないように、変数にキャプチャします。
あなたが何をしようとしているのか完全にはわかりません。保存されていない変更がある間は、アイテムの削除に進まないようです。ユーザーがそれを承認した場合、保存されていない変更を保存します。次に、ユーザーに削除の確認を求めます。ユーザーが保留中の変更の保存を拒否した場合は、削除プロセスを開始することもできません。
私が正しく理解していれば、次のようなものが必要だと思います。
_var self = this; // WHAT IS THIS? I don't know but capture it as 'self'
function saveBeforeDeleting() {
return saveIfNeeded().then(deleteIfConfirmed);
}
function saveIfNeeded() {
// no need to save; return resolved promise
if (!self.hasChanges()) return Q();
var dialogPromise = app.showMessage(
'Changes must be saved before removing external accounts. '+
'Would you like to save your changes now?',
'Unsaved Changes...', ['Yes', 'No']
);
// When the user replies, either save or return a rejected promise
// (which stops the flow)
return dialogPromise.then(function (selectedOption) {
return (selectedOption === 'Yes') ? self.save() : Q.reject();
});
}
function deleteIfConfirmed() {
var dialogPromise = app.showMessage(
'Are you sure you want to delete this item?',
'Delete?',
['Yes', 'No']
);
return dialogPromise.then(function (selectedOption) {
return (selectedOption === 'Yes') ? deleteIt() : Q.reject();
});
function deleteIt() {
item.entityAspect.setDeleted();
return datacontext.saveChanges().then(logAndRefresh);
}
function logAndRefresh() {
logger.logNotificationInfo(
'Item deleted.',
'',
router.activeInstruction().config.moduleId
);
return self.refresh(true));
}
}
_
明らかに、私はこのコードをテストしていません。それをインスピレーションと考えてください。
Promiseでエラーをスローすると、プロセスは最初の.fail/.catchハンドラーに直接ジャンプし、その間の.thens()
をスキップします。
function AbortError() {}
MyClass.prototype.delete = function() {
var p = Q();
var self = this;
if( this.hasChanges() ) {
p = app.showMessage('...', '...', ['Yes', 'No'])
.then(function(answer){
if( answer === "Yes") {
return self.save(); //I assume save returns a promise
}
throw new AbortError();
});
}
return p
.then(function() {
return app.showMessage('...', '...', ['Yes', 'No'])
})
.then(function(answer) {
if( answer === "yes") {
item.entityAspect.setDeleted();
return datacontext.saveChanges();
}
throw new AbortError();
})
.then(function(){
logger.logNotificationInfo('Item deleted.', '', router.activeInstruction().config.moduleId);
self.refresh(true);
})
.fail(function(e){
//kris please provide typed .catch feature :(
if( !(e instanceof AbortError) ) {
throw e;
}
});
};
一般に、すぐに解決される関数であっても、常にpromiseを返す関数を作成する必要があります。つまり、「return Q.resolve(someData)」です。
だから私は次のようなことを試してみます。以下の追加の「return」ステートメントに注意してください。
function complexSave() {
return saveIfNeeded().then(confirmDelete);
}
// returns a promise
function saveIfNeeded() {
if (this.hasChanges()) {
return app.showMessage('Changes must be saved before removing external accounts. Would you like to save your changes now?', 'Unsaved Changes...', ['Yes', 'No']).
then(function (selectedOption) {
if (selectedOption === 'Yes') {
return this.save();
} else {
return Q.resolve(false)
}
});
else {
return Q.resolve(false);
}
}
// returns a promise
function confirmDelete() {
return app.showMessage('Are you sure you want to delete this item?', 'Delete?', ['Yes', 'No'])
.then(function (selectedOption) {
if (selectedOption === 'Yes') {
item.entityAspect.setDeleted();
return datacontext.saveChanges()
.then(function () {
logger.logNotificationInfo('Item deleted.', '', router.activeInstruction().config.moduleId);
return Q.resolve(this.refresh(true));
}.bind(this));
} else {
return Q.resolve(false);
}
}.bind(this));
}