Closed riophae closed 12 years ago
Pause is useful when you have to ask the user for some information that the process will continue with, or ask the user to do something before process resumed. End is a simple version of pause. It can be used for ending process when severe error occurs.
There is an example including two versions of code showing timeline: http://pastebin.com/QCbwx2Bs
You can see that the former is more clear and easy to control.
Hmmm, I see. If I write code for the use case, I do like:
function confirmAuthorization () {
var d = new Deferred();
alert('You have to authorize this application before starting!');
form.bind('submit', function () {
d.call($(this).find('input[name=code]').val());
return false;
});
return d;
}
next(function() {
return http.get('http://example.com/get_access_token');
}).
error(function() {
return confirmAuthorization();
}).
next(function(access_token) {
// do someting with the access token we've got
return http.get('http://example.com/api/get_timeline.json');
}).
error(function() {
alert('Service unavailable. Check the network connection please.');
this.cancel();
}).
next(function(data) {
// process data and error may occur here
}).
error(function(e) {
alert(e);
this.cancel();
}).
next(function(processed_data) {
// show timeline
});
Is this bad for you?
It works, but not for some other cases where you don't have (or want) a confirmAuthorization which returns a deferred. Pause is easier to use and understand, and works all the time.
var d = new Deferred;
d.
next(function(fun) {
return fun();
}).
next(function(v) {
// process data here
// it's not stable and errors may occur too
return v;
}).
error(function(e) {
alert('An error occurs!');
return this.cancel();
}).
next(function(v) {
alert('Done: ' + v);
}).
error(function(e) {
alert('An error occurs!');
return this.cancel();
});
d.call(function() {
throw 'error!';
});
// => 'An error occurs!'
d.call(function() {
return 'everything is okay!';
});
// => nothing happened strangely
Just replace 'this.cancel()' with 'this.end()' and run it a second time.
d.call(function() {
throw 'error!';
});
// => 'An error occurs!'
d.call(function() {
return 'everything is okay!';
});
// => 'Done: everything is okay!'
This time it works fine! :)
next(function() {
// do someting
return 'some words';
}).
next(function(data) {
switch (typeof data) {
case 'string':
// do something with data
break;
case 'object':
// do something with data
break;
case 'number':
// do something with data
break;
}
return data;
}).
next(function(v) {
alert('Result: ' + v);
});
To make the structure of code more clear, we can rewrite it by this way:
next(function() {
// do someting
return 'some words';
}).
next(function(v) {
var d = new Deferred;
switch (typeof v) {
case 'string':
handler1(d, v);
break;
case 'object':
handler2(d, v);
break;
case 'number':
handler3(d, v);
break;
}
return d;
}).
next(function(v) {
alert('Result: ' + v);
});
function handler1(d, data) {
next(function() {
// process data
return data;
}).
next(function(v) {
d.call(v);
});
}
In this case, you have to pass the value and the deferred to every handler, and each of the handlers has to call back the deferred to continue the process. It's really ugly, isn't it? Now let's see what helps pause can provide.
next(function() {
// do someting
return 'some words';
}).
next(function(v) {
return this.pause('wait', function() {
switch (typeof v) {
case 'string':
handler1();
break;
case 'object':
handler2();
break;
case 'number':
handler3();
break;
}
});
}).
next(function(v) {
alert('Result: ' + v);
});
function handler1() {
Deferred.paused['wait'].resume(function(data) {
// process data
return data;
});
}
You can see that pause caches values and even statuses of deferreds. It's easy for you to continue the process with wanted ones and even then pause the process again! So pause makes it possible to create forkd deferreds. This can be very useful when organizing a complex logic.
Is this ignored?
Hmm. I want to keep the core Deferred object small, so I'm not in the mood.
For example, If a function have resolve a problem which is not possible without it, I think more seriously.
But in this case, maybe there are more elegant way to resolve it without expand Deferred's prototype.
Thanks.
Are there any concrete use cases for pause or end?