tl; dr :我正在寻找一种方法让第一个.then
回调对传递给后续链接事件的数据进行更改。
我有一个封装了一些异步操作的库。
dudetools.getDude(2); // causes an XHR against REST resource "Dude" for row id 2
出于令人敬畏的目的,dudetools.getDude
返回基础$.ajax
调用创建的承诺。因此,我可以做以下事情:
dudetools.getDude(dudeId).done(function(dudeData) { /* do stuff with dude's data */ });
现在我正在尝试修改dudetools
,以便在继续沿着承诺链继续对响应数据进行一些方便的数据按摩。我希望这种按摩能够普遍实现,而不需要代码请求它甚至不知道它。
因为dudetools
实现不能与所有调用代码共享闭包,所以我希望利用这样一个事实:在JavaScript中,非标量总是通过引用而不是值传递。
考虑:
var urStuff = {};
function wreck(x) {
x.isWrecked = 'so wrecked';
}
wreck(urStuff);
// urStuff.isWrecked === 'so wrecked' ^.^
我敢你试试。
所以,我希望这会奏效:
dudetools = {
'getDude': function(dudeId) {
return $.ajax('/api/Dude/' + dudeId).then(function(dudeData) {
// I'm so clever!
dudeData.isDuplicated = dudeData.isDuped && dudeData.drillDown > 5;
});
}
}
当然,它不起作用。我的聪明代码正在执行(我已经看过了),并且它得出了正确的结论,但链中的后续延迟事件从未看到修改。即:
$.when(
dudetools.getDude(dudeId)
).done(function(mysteriouslyUnmodifiedInfo) {
/* the info passed to this function is mysteriously unmodified! HALP */
});
有什么建议吗?有没有办法完成我追求的目标?
另外:我对一般的承诺仍然有点新意,而且我对Deferreds,Promises和相关结构之间差异的把握仍然有些模糊,所以我非常感谢你努力做到明确在向我解释我是如何破坏一切时明确的。
非常感谢。
编辑:更新以反映dudetools.getDude
返回承诺而不是延迟的事实。因为我现在(大部分)都了解其中的差异。
答案 0 :(得分:1)
.then
的神奇之处在于它将其返回值传递到 next 回调参数中。
如果你没有退回你的对象(即使你没有改变任何东西),那么默认情况下会返回undefined
。
do_something()
.then(function (json) { return JSON.parse(json); })
.then(function (response) { return response.data; })
.then(function (data) { data.tweaked = true; return data; });
答案 1 :(得分:0)
您需要返回自己的新Deferred.promise()
对象。
http://api.jquery.com/deferred.promise/
dudetools = {
'getDude': function(dudeId) {
var dfd = new jQuery.Deferred();
$.ajax('/api/Dude/' + dudeId).then(function(dudeData) {
dudeData.isDuplicated = dudeData.isDuped && dudeData.drillDown > 5;
// I'm so clever!
dfd.resolve(dudeData);
});
return dfd.promise();
}
}
希望有所帮助。