[英]How to correctly chain conditional(?) promises with Q.js
如果這是一個簡單的誤解,我還沒有完全理解承諾,所以道歉。
我有一個刪除頁面上的項目的功能,但我有一個特定的行為取決於頁面的狀態。 Psuedo代碼方式它是這樣的:
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
希望這是有道理的。 基本上如果有變化,必須先保存數據。 然后,如果數據已保存,或者如果沒有開始更改,則提示用戶確認刪除。 問題是我正在使用durandal和微風,我似乎無法將他們正確歸還的承諾鏈接起來。
我的功能目前看起來像這樣,我知道這是錯誤的,但我正在努力找出解決問題的方法。
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,然后解決它。 然后在該條件部分完成解析后,調用第二個提示,然后解析其中的所有承諾。
對不起我不認為這是非常明確的,但我認為這也是因為我並沒有完全遵循這里的鏈條。
任何幫助非常感謝! 謝謝。
克里斯是對的。 您不需要任何Q.resolve調用。
順便說一句,在你的情況下,返回一個具有已解決價值true
或false
的承諾是毫無意義的。 我擔心你會錯誤地認為返回false
會阻止鏈接then()
被調用。 不是這樣! 值為false
已解決的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()
任何.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;
}
});
};
一般來說,你想要創建函數來完成你的工作總是返回一個承諾,即使這是一個立即解決的,即“返回Q.resolve(someData)”。
所以我會嘗試以下內容。 請注意下面的額外“返回”聲明。
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));
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.