JQuery.Deferred(), затем, как разрешить с несколькими параметрами

Итак, мой API ожидает, что когда конкретная отложенная проблема будет решена, она получит 2 параметра.

fn().done(function(arg1, arg2) {
  console.log(arg1, arg2);
}).fail(function(err) {
  console.error(err);
});

Теперь, касаясь функции fn выше, сначала нужно дождаться, пока какой-либо другой отложенный запрос будет возвращен до разрешения.

function other() {
  // stubbed out to always resolve
  return $.Deferred().resolve().promise();
}

function fn() {
  return other().then(function() {
    return [1, 2];
  });
}

Но это не работает, потому что arg1 появится как [1, 2] и arg2 будет undefined. Я не могу понять, как вернуть что-то из аргумента функции фильтра Deferred.then() первого успеха, чтобы отложенная результирующая отложенная передача передавалась с несколькими аргументами.

Конечно, я могу это сделать:

function fn() {
  var done = $.Deferred();
  other().done(function(){
    done.resolve(1, 2);
  }).fail(function(){
    done.reject.apply(done, arguments);
  });
  return done.promise();
}

Но это не так элегантно, как использование .then(), и теперь мне нужно каждый раз беспокоиться об API отрицательного случая отказа, хотя я знаю, что я просто передаю отклоненное состояние через.

И да, я мог бы также изменить fn() api для решения с помощью массива, но я действительно надеюсь, что есть элегантное решение.

Ответ 1

Вам нужно будет вызывать resolve() или reject(), чтобы передать несколько аргументов.

.then() не содержит каких-либо механизмов для "распространения" возвращенной коллекции. Он просто сохранит коллекцию в качестве первого аргумента.

Но он будет взаимодействовать с возвратом Deferred или обещанием. Из абзаца начинающегося с " Как в jQuery 1.8" :

Эти функции фильтра могут возвращать новое значение, которое должно быть передано вместе с обещаниями .done() или .fail(), или , они могут возвращать другой наблюдаемый объект (Отложенный, Обещание и т.д.), который пройдет его разрешен/отклонен статус и значения для обещающих обратных вызовов.

Итак, вы можете использовать свой пример other() в качестве основы для fn(), чтобы он был достаточно кратким с другим Deferred():

function fn() {
    return other().then(function () {
        return $.Deferred().resolve(1, 2).promise();
    });
}

fn().then(function (a, b) {
    console.log(arguments.length, a, b); // 2 1 2
});

http://jsfiddle.net/cqac2/