使用promises构建高度交互的UI我有很多乐趣。但是,我遇到了一个棘手的情况。我有一个函数返回执行服务器更新的promise。我想使用后续承诺处理程序来更新客户端模型,然后向UI发出更新事件。这是我的代码:
function updateServer (action) {
return $.post(URL, { action: action })
.fail(function (error) {
console.log(error);
});
}
// An example action that might affect the server
_this.freeze = function (mode) {
updateServer("freeze").done(function (data) {
_this.model.data.status = data.status;
})
.done(function () {
$(window).trigger(Events.UpdateUI);
});
};
您会注意到我必须在freeze命令中发出更新事件。我宁愿在updateServer函数中这样做,以避免重复每个控制方法中的代码。
我想通过将模型更新函数作为参数传递给updateServer来实现这一点,但是,它似乎违反了我认为的承诺精神:
function updateServer (action, fn) {
return $.post(URL, { action: action })
.done(fn)
.done(function () {
$(window).trigger(Events.UpdateUI);
})
.fail(function (error) {
console.log(error);
});
}
// An example action that might affect the server
_this.freeze = function (mode) {
updateServer("freeze", function (data) {
_this.model.data.status = data.status;
});
};
我认为另一种方法是设计一种优先级较低的完成处理程序,这样就可以使我保持承诺可组合性的精神。我错过了什么,或者我是以“正确的方式”做到这一点吗?
谢谢你们!
答案 0 :(得分:1)
您不应该尝试在用于与服务器通信的函数内更新UI。这是Separation of Concerns的对立面。
如果你想要一种确保这些任务总是一起执行的方法,你可以创建另一个将这两个动作连接在一起并返回promise的函数,以便它可以被进一步链接。
编辑:根据您的评论,现在很清楚您希望将数据检索和UI更新作为一个整体保存在一起,但在之间执行另一个操作。在那种情况下,我会说解决方案是传递一个函数。只要您没有使用回调来控制整个执行流程,这仍然符合承诺的精神:
function updateServer (action) {
return $.post(URL, { action: action })
.fail(function (error) {
console.log(error);
});
}
function updateUI () {
$(window).trigger(Events.UpdateUI);
}
function updateServerAndRefreshUI (action, updateModel) {
return updateServer(action)
.done(updateModel)
.done(updateUI);
}
// An example action that might affect the server
_this.freeze = function (mode) {
updateServerAndRefreshUI("freeze", function (data) {
_this.model.data.status = data.status;
});
};
答案 1 :(得分:1)
我想你会想要使用一个帮助你整个行动的辅助函数:
function updateUIwith(result) {
return result.then(function() {
$(window).trigger(Events.UpdateUI);
}).fail(function(error) {
console.log(error);
});
}
现在你只需要写
function updateServer(action) {
return $.post(URL, {action: action})
}
// An example action that might affect the server
_this.freeze = function(mode) {
updateUIwith(updateServer("freeze").then(function(data) {
_this.model.data.status = data.status;
}));
};