Я только что использовал Deferred в реальном коде. В проекте jQuery Terminal у меня есть функция exec, которая вызывает команды, определенные пользователем (например, он вводил ее и нажимал ввод), я добавил Deferreds в API и вызвал exec с массивами. как это:
terminal.exec('command').then(function() {
terminal.echo('command finished');
});
или
terminal.exec(['command 1', 'command 2', 'command 3']).then(function() {
terminal.echo('all commands finished');
});
команды могут запускать асинхронный код, и exec должен вызывать код пользователя по порядку. Мой первый API использует пару вызовов паузы / возобновления, и в новом API я вызываю их автоматически, когда пользователь возвращает обещание. Таким образом, пользовательский код может просто использовать
return $.get('/some/url');
или
var d = new $.Deferred();
setTimeout(function() {
d.resolve("Hello Deferred"); // resolve value will be echoed
}, 500);
return d.promise();
Я использую такой код:
exec: function(command, silent, deferred) {
var d;
if ($.isArray(command)) {
return $.when.apply($, $.map(command, function(command) {
return self.exec(command, silent);
}));
}
// both commands executed here (resume will call Term::exec)
if (paused) {
// delay command multiple time
d = deferred || new $.Deferred();
dalyed_commands.push([command, silent, d]);
return d.promise();
} else {
// commands may return promise from user code
// it will resolve exec promise when user promise
// is resolved
var ret = commands(command, silent, true, deferred);
if (!ret) {
if (deferred) {
deferred.resolve(self);
return deferred.promise();
} else {
d = new $.Deferred();
ret = d.promise();
ret.resolve();
}
}
return ret;
}
},
dalyed_commands используется в функции возобновления, которая снова вызывает exec со всеми dalyed_commands.
и часть функции команд (я удалил не связанные части)
function commands(command, silent, exec, deferred) {
var position = lines.length-1;
// Call user interpreter function
var result = interpreter.interpreter(command, self);
// user code can return a promise
if (result != undefined) {
// new API - auto pause/resume when using promises
self.pause();
return $.when(result).then(function(result) {
// don't echo result if user echo something
if (result && position === lines.length-1) {
display_object(result);
}
// resolve promise from exec. This will fire
// code if used terminal::exec('command').then
if (deferred) {
deferred.resolve();
}
self.resume();
});
}
// this is old API
// if command call pause - wait until resume
if (paused) {
self.bind('resume.command', function() {
// exec with resume/pause in user code
if (deferred) {
deferred.resolve();
}
self.unbind('resume.command');
});
} else {
// this should not happen
if (deferred) {
deferred.resolve();
}
}
}