问题
the simplest example of what I'm looking for is this:
var messageLoader = $.post("api/user/messages", {api:data})
messageLoader.done(function(data){
//do something
});
This works brilliantly, but only once. If I want to update the data, I have to redefine everything.
I can't seem to find any call for the Deferred Object that let's me restart it. i.e. messageLoader.redo()
, which ideally would re-do the POST request, and subsequently call the same "done" handler without me having to re-define it.
I could put it all in a function and simply call that function again, but that's not what I'm looking for, because I would further want to do this:
var messageLoader = $.post("api/user/messages", {api:data})
var friendRequestLoader = $.post("api/user/friendrequests", {api:data})
$.when(messagesLoader, friendRequestLoader)
.done(function (messages, friendRequests) {
// update display of messages and friend requests
// attach Handlers
});
$("#updateMessages").click(function(){
messageLoader.redo() // This doesn't exist
})
The idea is that clicking $("#updateMessages")
would re-do just that request, then the $.when()
handler would use the new messageLoader
data, and the original friendRequestLoader
data.
I've looked in the docs for something like this but haven't found anything. Perhaps someone here knows if it exists, or a way to accomplish the same thing.
回答1:
I'm pretty sure the Deferred class just isn't designed to work the way you want, because they're intended to be one-time use objects. I even sat in on a whole session on Deferreds at jQueryConf, and re-using them wasn't even mentioned.
Furthermore, as you can see from the Deferred API page:
http://api.jquery.com/category/deferred-object/
there is no restart method. You might be able to manually change the properties of a Deferred to simulate "restarting" it, but really I think you should make your own class at this point, as you're really looking for something Deferred doesn't offer.
You have to keep in mind, Deferred is designed so that you can say "hey Deferred, go do something" (new Deferred().when(something)
), and then you can say "hey Deferred, when that's done do X" (deferred.then(x)
). Now, when you say "when that's done", ie. when you make a .then
call, the Deferred can be in two states: done, or not, but the call works in either case (if it's done it resolves immediately, otherwise it waits to be triggered).
Now, if a Deferred could have a third state ("done but restarted"), the .then
call wouldn't know what to do: does "done but restarted" mean that it should fire it's thens, or not? The answer depends on whether you made the .then
call before or after the restart call, and as you're hopefully seeing that all has the potential to get rather complicated (especially if you allow for multiple restarts).
Rather than deal with all that (none of which was needed for $.ajax
) the jQuery folks went with the (comparatively simple) current Deferred implementation, and I think it was the right call on their part.
回答2:
You can try this method:
function Defer() {
$.when(messageLoader, friendRequestLoader)
.done(function (messages, friendRequests) {
console.log("M : " + messages[0].test);
console.log("F : " + friendRequests[0].test);
});
}
$("#updateMessages").click(function(){
messageLoader = $.post("api/user/messages", {api:data});
Defer();
});
This will allow you to reload one while keeping the data from the other.
回答3:
It's as simple as creating a function and recalling that. It's not possible to keep $.post alive because the http is a static protocol.
var messageLoader;
var friendRequestLoader;
updateMessages();
function updateMessages(){
messageLoader= $.post("api/user/messages", {api:data})
friendRequestLoader = $.post("api/user/friendrequests", {api:data})
}
$.when(messagesLoader, friendRequestLoader)
.done(function (messages, friendRequests) {
// update display of messages and friend requests
// attach Handlers
});
$("#updateMessages").click(function(){
updateMessages(); // This doesn't exist
})
来源:https://stackoverflow.com/questions/13732713/reuse-jquery-post-jquery-deferred-object