Если вы находитесь за прокси-сервером, перед началом установки вы должны выполнить дополнительные шаги по настройке. Вы должны установить переменную окружения http_proxy на адрес прокси-сервера. Используя bash, это выполняется с помощью команды
export http_proxy="http://user:pass@my.site:port/"
. Вы также можете указать параметр
--proxy=[user:pass@]url:port
в pip. Часть [user:pass@]
не является обязательной.
Чтобы передать массив значений в любую функцию , которая обычно ожидает их отдельных параметров, используйте Function.prototype.apply
, поэтому в этом случае вам понадобятся:
$.when.apply($, my_array).then( ___ );
См. http://jsfiddle.net/YNGcm/21/
В ES6 вы можете использовать оператор ...
spread :
$.when(...my_array).then( ___ );
В любом случае, поскольку маловероятно, что вы заранее узнаете, сколько формальных параметров потребует обработчик .then
, этот обработчик должен будет обработать массив arguments
, чтобы получить результат каждого обещания.
У меня был случай, очень похожий, когда я отправлял в каждом цикле, а затем устанавливал разметку html в некоторых полях из чисел, полученных из ajax. Затем мне нужно было сделать сумму (обновленных) значений этих полей и поместить в полное поле.
Таким образом, проблема заключалась в том, что я пытался делать сумму на всех числах, но до сих пор нет данных от вызовов async ajax. Мне нужно было выполнить эту функциональность в нескольких функциях, чтобы повторно использовать код. Моя внешняя функция ожидает данных до того, как я перейду и сделаю некоторые вещи с полностью обновленным DOM.
// 1st
function Outer() {
var deferreds = GetAllData();
$.when.apply($, deferreds).done(function () {
// now you can do whatever you want with the updated page
});
}
// 2nd
function GetAllData() {
var deferreds = [];
$('.calculatedField').each(function (data) {
deferreds.push(GetIndividualData($(this)));
});
return deferreds;
}
// 3rd
function GetIndividualData(item) {
var def = new $.Deferred();
$.post('@Url.Action("GetData")', function (data) {
item.html(data.valueFromAjax);
def.resolve(data);
});
return def;
}
Вы можете применить метод when
к вашему массиву:
var arr = [ /* Deferred objects */ ];
$.when.apply($, arr);
Обходные пути выше (спасибо!) неправильно решают проблему возврата объектов, предоставленных методу отложенного resolve()
, потому что jQuery вызывает обратные вызовы done()
и fail()
с отдельными параметрами, а не с массивом. Это означает, что мы должны использовать псевдо-массив arguments
, чтобы получить все разрешенные / отклоненные объекты, возвращенные массивом отложенных, что является уродливым:
$.when.apply($,deferreds).then(function() {
var objects=arguments; // The array of resolved objects as a pseudo-array
...
};
Поскольку мы прошли в массиве отложенных , было бы неплохо вернуть массив результатов. Также было бы неплохо вернуть фактический массив вместо псевдо-массива, чтобы мы могли использовать такие методы, как Array.sort()
.
Вот решение, основанное на методе метода [.9], который обращается к этим Проблемы:
// Put somewhere in your scripting environment
if (typeof jQuery.when.all === 'undefined') {
jQuery.when.all = function (deferreds) {
return $.Deferred(function (def) {
$.when.apply(jQuery, deferreds).then(
function () {
def.resolveWith(this, [Array.prototype.slice.call(arguments)]);
},
function () {
def.rejectWith(this, [Array.prototype.slice.call(arguments)]);
});
});
}
}
Теперь вы можете просто передать массив отложенных / обещаний и вернуть массив разрешенных / отвергнутых объектов в ваш обратный вызов, например:
$.when.all(deferreds).then(function(objects) {
console.log("Resolved objects:", objects);
});
var toArray = function (args) { return deferreds.length > 1 ? $.makeArray(args) : [args]; }
вместо Array.prototype.slice.call
.
– Luan Nico
14 January 2016 в 12:47
В качестве простой альтернативы, которая не требует $.when.apply
или array
, вы можете использовать следующий шаблон для создания единого обещания для нескольких параллельных обещаний:
promise = $.when(promise, anotherPromise);
, например
function GetSomeDeferredStuff() {
// Start with an empty resolved promise (or undefined does the same!)
var promise;
var i = 1;
for (i = 1; i <= 5; i++) {
var count = i;
promise = $.when(promise,
$.ajax({
type: "POST",
url: '/echo/html/',
data: {
html: "<p>Task #" + count + " complete.",
delay: count / 2
},
success: function (data) {
$("div").append(data);
}
}));
}
return promise;
}
$(function () {
$("a").click(function () {
var promise = GetSomeDeferredStuff();
promise.then(function () {
$("div").append("<p>All done!</p>");
});
});
});
promise = promise.then(newpromise)
then()
вызовов аналогичным образом. Поведение с $.when
должно действовать так, как оно является параллельным (не цепным). Попробуйте, прежде чем выбрасывать полезную альтернативу, поскольку она работает :)
– Gone Coding
9 July 2015 в 09:10
Если вы используете angularJS или какой-то вариант библиотеки обещаний Q, то у вас есть метод .all()
, который решает эту точную проблему.
var savePromises = [];
angular.forEach(models, function(model){
savePromises.push(
model.saveToServer()
)
});
$q.all(savePromises).then(
function success(results){...},
function failed(results){...}
);
см. полный API:
https://github.com/kriskowal/q/wiki/API-Reference#promiseall
Если вы транслируете и имеете доступ к ES6, вы можете использовать синтаксис распространения, который специфически применяет каждый итеративный элемент объекта как дискретный аргумент, как раз $.when()
нуждается в нем.
$.when(...deferreds).done(() => {
// do stuff
});
При вызове нескольких параллельных вызовов AJAX у вас есть две возможности для обработки соответствующих ответов.
Promises'
и $.when
, который принимает promise
s, и его обратный вызов .done
вызывается, когда все promise
s успешно возвращаются с соответствующими ответами. Пример
function ajaxRequest(capitalCity) {
return $.ajax({
url: 'https://restcountries.eu/rest/v1/capital/'+capitalCity,
success: function(response) {
},
error: function(response) {
console.log("Error")
}
});
}
$(function(){
var capitalCities = ['Delhi', 'Beijing', 'Washington', 'Tokyo', 'London'];
$('#capitals').text(capitalCities);
function getCountryCapitals(){ //do multiple parallel ajax requests
var promises = [];
for(var i=0,l=capitalCities.length; i<l; i++){
var promise = ajaxRequest(capitalCities[i]);
promises.push(promise);
}
$.when.apply($, promises)
.done(fillCountryCapitals);
}
function fillCountryCapitals(){
var countries = [];
var responses = arguments;
for(i in responses){
console.dir(responses[i]);
countries.push(responses[i][0][0].nativeName)
}
$('#countries').text(countries);
}
getCountryCapitals()
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<h4>Capital Cities : </h4> <span id="capitals"></span>
<h4>Respective Country's Native Names : </h4> <span id="countries"></span>
</div>
for ... in
на массиве ?!)
– Alnitak
13 October 2015 в 19:39
(not recommended)
2. Не согласен - for ... in
в порядке, потому что массив содержит только те свойства, которые нуждаются (никаких дополнительных свойств). в любом случае
– vinayakj
13 October 2015 в 19:45
Array.prototype
. В любом случае для кода, не относящегося к производительности, было бы лучше использовать .map
вместо цикла for
/ push
, например. var promises = capitalCities.map(ajaxRequest); $.when.apply($, promises).then(fillCountryCapitals)
- выполненная работа.
– Alnitak
13 October 2015 в 19:56
$
vsnull
в качестве первого параметра стоит прочитать. В этом конкретном случае это не имеет значения. – Alnitak 11 April 2011 в 21:50$
меньше набирает, чемnull
, и вы будете в безопасности при изменении реализации$.when
(не так, вероятно, в этом случае, но почему бы не оставитьthis
неизменным по умолчанию). – Tomasz Zielinski 18 December 2012 в 15:07