Получение JSON из нескольких источников [дубликат]

Если вы находитесь за прокси-сервером, перед началом установки вы должны выполнить дополнительные шаги по настройке. Вы должны установить переменную окружения http_proxy на адрес прокси-сервера. Используя bash, это выполняется с помощью команды

export http_proxy="http://user:pass@my.site:port/" 

. Вы также можете указать параметр

--proxy=[user:pass@]url:port 

в pip. Часть [user:pass@] не является обязательной.

403
задан Alnitak 12 October 2015 в 10:21
поделиться

9 ответов

Чтобы передать массив значений в любую функцию , которая обычно ожидает их отдельных параметров, используйте Function.prototype.apply, поэтому в этом случае вам понадобятся:

$.when.apply($, my_array).then( ___ );

См. http://jsfiddle.net/YNGcm/21/

В ES6 вы можете использовать оператор ... spread :

$.when(...my_array).then( ___ );

В любом случае, поскольку маловероятно, что вы заранее узнаете, сколько формальных параметров потребует обработчик .then, этот обработчик должен будет обработать массив arguments, чтобы получить результат каждого обещания.

660
ответ дан Alnitak 20 August 2018 в 09:02
поделиться
  • 1
    Это работает, потрясающе. :) Я поражен, что я не смог переделать такое простое изменение через Google! – adamjford 11 April 2011 в 21:42
  • 2
  • 3
    @Alnitak: Я немного смущен, что не знал об этом методе, учитывая, как долго я писал JavaScript сейчас! – adamjford 11 April 2011 в 21:49
  • 4
    FWIW, ссылка в ответе Эли на более ранний вопрос с обсуждением прохождения $ vs null в качестве первого параметра стоит прочитать. В этом конкретном случае это не имеет значения. – Alnitak 11 April 2011 в 21:50
  • 5
    @Alnitak: Да, но $ меньше набирает, чем null, и вы будете в безопасности при изменении реализации $.when (не так, вероятно, в этом случае, но почему бы не оставить this неизменным по умолчанию). – Tomasz Zielinski 18 December 2012 в 15:07

У меня был случай, очень похожий, когда я отправлял в каждом цикле, а затем устанавливал разметку 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;
    }
0
ответ дан Cameron Forward 20 August 2018 в 09:02
поделиться

Вы можете применить метод when к вашему массиву:

var arr = [ /* Deferred objects */ ];

$.when.apply($, arr);

Как вы работаете с массивом отложенных jQuery?

37
ответ дан Community 20 August 2018 в 09:02
поделиться
  • 1
    Вау, сегодня я медленный ... – Eli 11 April 2011 в 21:48
  • 2
    Я действительно видел этот вопрос, но, я думаю, все дополнительные детали в этом вопросе вызвали ответ на мою проблему (которая была там прямо), чтобы лететь прямо над моей головой. – adamjford 11 April 2011 в 21:50
  • 3
    @adamjford, если это заставляет вас чувствовать себя лучше, я нашел ваш вопрос более удобным для использования (и сначала в моем конкретном поиске Google для этой точной проблемы). – patridge 10 November 2011 в 23:09
  • 4
    @patridge: Приятно слышать, что это помогло вам! – adamjford 11 November 2011 в 00:35
  • 5
    Это отличный ответ, но мне было непонятно, как это применимо к примеру в исходном вопросе. После консультации с связанным вопросом стало ясно, что строка «$. Когда (отложен) .done (function () {« просто должна быть изменена на «$». Когда. Appply ($, отложенные) .done (функция () {«Правильно? – Garland Pope 11 August 2018 в 18:18

Обходные пути выше (спасибо!) неправильно решают проблему возврата объектов, предоставленных методу отложенного 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);
});
98
ответ дан fernandosavio 20 August 2018 в 09:02
поделиться
  • 1
    Возможно, вы захотите использовать resolWith и rejectWith именно так, что вы получите те же оригинальные отсрочки, что и «this» deferred.resolveWith (это [Array.prototype.slice.call (arguments)]) и т. Д. – Jamie Pate 21 August 2013 в 21:49
  • 2
    Есть только небольшая проблема с вашим кодом, когда в массиве есть только один элемент, массив результатов возвращает именно этот результат, а не массив с одним элементом (который разбивает код, ожидающий массив). Чтобы исправить это, используйте эту функцию var toArray = function (args) { return deferreds.length > 1 ? $.makeArray(args) : [args]; } вместо Array.prototype.slice.call. – Luan Nico 14 January 2016 в 12:47
  • 3
    Хм, похоже, он не поймал ни одного 404-го. – t.mikael.d 13 August 2016 в 14:02
  • 4
    Найденная причина, .fail должен быть .reject вместо этого - так что он может поймать 404. – t.mikael.d 13 August 2016 в 14:10
  • 5
    Именно то, что мне нужно, спасибо! – acaputo 1 March 2018 в 17:45

В качестве простой альтернативы, которая не требует $.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)
  • Недостатком является то, что он создает дополнительное обещание объекты за кулисами и любые параметры, переданные в конце, не очень полезны (поскольку они вложены внутри дополнительных объектов). Для того, что вам нужно, хотя оно короткое и простое.
  • Поверхность - это не требует управления массивами или массивами.
5
ответ дан Gone Coding 20 August 2018 в 09:02
поделиться
  • 1
    Исправьте меня, если я ошибаюсь, но ваш подход эффективно вложен в $ .when ($ .when ($ .when (...))), поэтому вы закончите рекурсивно вложенные 10 уровней, если есть 10 итераций. Это не кажется очень параллельным, так как вам нужно ждать, пока каждый уровень вернет вложенное обещание ребенка, прежде чем он сможет вернуть свое обещание. Я думаю, что подход массива в принятом ответе намного чище, поскольку он использует гибкое поведение параметров, встроенное в метод $ .when (). – Anthony McLin 9 July 2015 в 03:46
  • 2
    @AnthonyMcLin: это призвано обеспечить более простую альтернативу кодированию, а не лучшую производительность (что незначительно для большинства асинхронных кодировок), как это делается с цепочкой then() вызовов аналогичным образом. Поведение с $.when должно действовать так, как оно является параллельным (не цепным). Попробуйте, прежде чем выбрасывать полезную альтернативу, поскольку она работает :) – Gone Coding 9 July 2015 в 09:10
  • 3
    @Alnitak: Лошади для курсов. Вы, безусловно, имеете право на мнение, но вы, очевидно, не использовали его сами. Мое собственное мнение основано на практическом использовании этого метода. Он работает и использует, поэтому зачем выкидывать инструмент из панели инструментов на основе преувеличений, таких как «нагрузки оговорок», (один) и «ничего не решает». (не верно - он устраняет обработку массива и упрощает цепочку параллельных обещаний, где возвращаемые значения не нужны, что, как вам известно, редко используется в случаях параллельной обработки). Предполагается, что нисходящие нити для «этого ответа не являются полезными». :) – Gone Coding 14 October 2015 в 09:02
  • 4
    Привет @GoneCoding. Могу ли я попросить вас не добавлять комментарии к комментариям к ответам? Это подходит для комментариев, но в остальном это шум, который отвлекает от хорошего контента. Благодарю. – halfer 12 June 2016 в 10:04
  • 5
    @halfer: Я больше не публикую, но меня раздражает невежество, проявленное к чему-то оригинальному. Сохранять все новые идеи для себя в наши дни :) – Gone Coding 12 June 2016 в 10:19

Если вы используете 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

https://docs.angularjs.org/ апи / нг / услуги / $ д

3
ответ дан Pang 20 August 2018 в 09:02
поделиться
  • 1
    Это совершенно не имеет значения. – Benjamin Gruenbaum 22 April 2015 в 17:21
  • 2
    @BenjaminGruenbaum Как так? Все библиотеки javascript-соглашений совместно используют аналогичный API, и нет ничего плохого в том, чтобы показывать разные реализации. Я достиг этой страницы, ища ответ для углового, и я подозреваю, что многие другие пользователи достигнут этой страницы и не обязательно будут в среде jquery. – mastaBlasta 27 April 2015 в 14:04
  • 3
    – Benjamin Gruenbaum 27 April 2015 в 14:05

Если вы транслируете и имеете доступ к ES6, вы можете использовать синтаксис распространения, который специфически применяет каждый итеративный элемент объекта как дискретный аргумент, как раз $.when() нуждается в нем.

$.when(...deferreds).done(() => {
    // do stuff
});

Ссылка MDN - Синтаксис распространения

1
ответ дан relic 20 August 2018 в 09:02
поделиться

При вызове нескольких параллельных вызовов AJAX у вас есть две возможности для обработки соответствующих ответов.

  1. Использовать синхронный вызов AJAX / один за другим / не рекомендуется
  2. Использовать 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>

5
ответ дан vinayakj 20 August 2018 в 09:02
поделиться
  • 1
  • 2
    Я думал, что подробное объяснение с примером было бы лучше, с доступными опциями. И для этого я не думаю, что downvote был необходим. – vinayakj 13 October 2015 в 19:07
  • 3
    downvote был для 1. даже предлагая синхронизацию (хотя и с рекомендацией не делать этого) 2. код низкого качества в примерах (в том числе for ... in на массиве ?!) – Alnitak 13 October 2015 в 19:39
  • 4
    1. Согласовано, должно было быть (not recommended) 2. Не согласен - for ... in в порядке, потому что массив содержит только те свойства, которые нуждаются (никаких дополнительных свойств). в любом случае – vinayakj 13 October 2015 в 19:45
  • 5
    Re: 2 - проблема в том, что он может быть скопирован другими людьми, которые не могут сделать эту гарантию, или были достаточно глупыми, чтобы добавить к Array.prototype. В любом случае для кода, не относящегося к производительности, было бы лучше использовать .map вместо цикла for / push, например. var promises = capitalCities.map(ajaxRequest); $.when.apply($, promises).then(fillCountryCapitals) - выполненная работа. – Alnitak 13 October 2015 в 19:56
3
ответ дан Pang 31 October 2018 в 07:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: