2015-09-10 2 views
3

У меня есть следующий метод службы:AngularJS прохождение более чем одно значение обещают успех обратного вызова

ResourcesService.prototype.list = function() 
{ 
     var deferred = q.defer(); 
     var settings = fetchSettings(); 
     restService.getAll(resourceName, settings) 
     .then(function (response) { 
      deferred.resolve(response.data, { 
       count: response.headers('cr_count'), 
       total: response.headers('cr_total'), 
       last: response.headers('cr_last') 
      }); 
     }, function (error) { 
      deferred.reject(error.statusText); 
     }); 
     return deferred.promise; 
} 

Как вы можете видеть, я передаю два значения deferred.resolve, которые response.data и объекта метаданных.

Up в стеке вызовов у меня есть:

//"scenes" is an object that inherits from ResourcesService 
scenes 
.withLanguage('en-us') 
.sort('creation') 
.size(2) 
.list() 
.then(function (firstPage, metadata) { 
    //firstPage is the "response.data" from previous method 
    //metadata is undefined, but should be an object with all the values from the headers 
}); 

Почему metadata не определено? Я отлаживал ResourcesService, и заголовки читаются просто отлично, но переданный объект как аргумент deferred.resolve не передается моей функции обратного вызова.

Поддерживает ли deferred.resolve только один аргумент для обратного вызова? Должен ли я помещать эти метаданные в один и тот же объект вместе с ответом?

+1

Избегайте [отложенные антипаттерны] (http://stackoverflow.com/q/23803743/1048572). – Bergi

+0

См. Также [javascript, не передающий все аргументы (используя 'Q')] (http://stackoverflow.com/q/17970420/1048572) (' $ q' работает одинаково в этом отношении) – Bergi

ответ

3

Вы не можете передать более одного параметра в then callback, только тот, который ожидается и рассматривается. Однако вы можете решить свое обещание с помощью объекта. Например:

ResourcesService.prototype.list = function() { 

    var settings = fetchSettings(); 
    return restService.getAll(resourceName, settings).then(function (response) { 
     return { 
      data: response.data, 
      metadata: { 
       count: response.headers('cr_count'), 
       total: response.headers('cr_total'), 
       last: response.headers('cr_last') 
      } 
     };  
    }, function (error) { 
     throw new Error(error.statusText); 
    }); 
} 

Обратите внимание, что я также фиксированной deferred anti-pattern в вашем коде, вам не нужен фиктивный отложенный объект, потому что у вас уже есть обещание вы можете вернуться.

Тогда вы бы использовать его как это:

scenes 
.withLanguage('en-us') 
.sort('creation') 
.size(2) 
.list() 
.then(function (response) { 
    var firstPage = response.data, 
     metadata = response.metadata; 
}); 
+0

Этот подход намного приятнее чем у меня, но почему вы бросаете исключение, когда есть ошибка? Я попытался вернуть 'error.statusText', но мой обратный вызов ошибки никогда не выполняется. Вместо этого вызывается мой обратный вызов. Как я могу вызвать обратный вызов ошибки без использования 'q.reject'? –

+0

Именно поэтому я бросаю: потому что, если вы вернетесь - это означает, что вы обработали сбой, поэтому вы восстановили, а затем в последующих обратных вызовах вы не попадете в обработчик ошибок - потому что вы уже обработали ошибку. Поэтому в этом случае, если вы хотите распространять erro по цепочке, вы либо $ q.reject, либо throw. Вы можете даже просто «выбросить error.statusText;», если хотите. – dfsq

+0

Я вижу. Спасибо за ваш ответ!. Я закончил делать это по-своему, и мне это нравится больше, чем раньше, и я больше не буду зависеть от службы '$ q'. –

1

Хотя @dsfq прав насчет не решения с более чем одним аргументом, если вы используете q, вы можете также обернуть разрешенные значения в массиве и используйте .spread() вместо .then(), чтобы разделить их по аргументам.

Создано:

.then(function (response) { 
     // Resolve with a single array 
     deferred.resolve([response.data, { 
      count: response.headers('cr_count'), 
      total: response.headers('cr_total'), 
      last: response.headers('cr_last') 
     }]); 
    } 

Потребляемый:

scenes 
.withLanguage('en-us') 
.sort('creation') 
.size(2) 
.list() 
// .spread() instead of .then() 
.spread(function (firstPage, metadata) { 
    // Works as expected 
}); 
Смежные вопросы