Загружать коллекции AJAX по порядку в JavaScript - PullRequest
0 голосов
/ 12 октября 2018

Как убедиться, что в JavaScript (jquery) некоторые действия выполняются одно за другим в порядке.

Скажем, мне нужно загрузить schools коллекцию ДО загрузки teachers, чтобы получить myTeacher.SchoolName = schools[myTeacher.SchoolId].name;

Псевдокод ниже:

const studentsUrl='api/students', teachersUrl='api/teachers', schoolsUrl='api/schools';
let students = null, teachers = null, schools = null;

$(document).ready(function () {
    getSchools(); 
    getTeachers(); 
    getStudents(); 
});

function getSchools() {
    $.get(schoolsUrl, function (data) {
            window.schools = data;
        });
}

function getTeachers() {
    $.get(teachersUrl, function (data) {
            window.teachers = data;

            // >>> SHOULD BE SURE, SCHOOLS already loaded!!!
            $.each(teachers, function (key, item) {
                item.school = schools[item.schoolId].name;
            });
        });
}

function getStudents() {
    $.get(studentsUrl, function (data) {
            window.students = data;

            // >>> SHOULD BE SURE, TEACEHRS already loaded!!!
            $.each(students, function (key, item) {
                item.teacher = teachers[item.teacherId].name;
            });
        });
}

PS.

Есть ли другой способ обеспечить порядок, кроме инкапсуляции одной функции в конце другой?

Ответы [ 6 ]

0 голосов
/ 12 октября 2018

Если вы хотите, чтобы они были в порядке (хотя я не уверен, что понимаю, почему, поскольку вы все равно извлекаете все школы / учителей / учащихся), вы можете просто сделать это.

Примечание : get* функции являются пустышками в следующем примере.Вместо этого просто верните результат $.get вызовов от них:

function getSchools() {
  return Promise.resolve({1: {name: 'school1'}});
}

function getTeachers() {
  return Promise.resolve({1: {name: 'teacher1', schoolId: 1}});
}

function getStudents() {
  return Promise.resolve({1: {name: 'student1', teacherId: 1}});
}

(async () => {
  const schools = await getSchools();
  const teachers = await getTeachers();
  const students = await getStudents();

    // Alternative for the $.each code
  Object.values(teachers).forEach(teacher => teacher.school = schools[teacher.schoolId].name);
  Object.values(students).forEach(student => student.teacher = teachers[student.teacherId].name);
  
  console.log(schools, teachers, students);
})();

Еще одно замечание: это код ES8, я опубликую не асинхронную / ожидающую версию, если вам потребуется поддержка старых браузеров и вы не можете использовать транспортер, такой как Babel.

Код, не зависящий от ES8 :

function getSchools() {
  return Promise.resolve({1: {name: 'school1'}});
}

function getTeachers() {
  return Promise.resolve({1: {name: 'teacher1', schoolId: 1}});
}

function getStudents() {
  return Promise.resolve({1: {name: 'student1', teacherId: 1}});
}

let schools = null, teachers = null, students = null;

getSchools().then(_schools => {
  schools = _schools;
  return getTeachers();
}).then(_teachers => {
  teachers = _teachers;
  return getStudents();
}).then(_students => {
  students = _students;

  for (var _ in teachers) {
    teachers[_].school = schools[teachers[_].schoolId].name;
  }
  for (var _ in students) {
    students[_].teacher = teachers[students[_].teacherId].name
  }

  console.log(schools, teachers, students);
});
0 голосов
/ 12 октября 2018

Как уже предлагали другие, вы можете связывать запросы.Я сделал несколько изменений в вашем коде.

  1. Добавлен Строгий режим Это помогает предотвратить ошибки
  2. Код, завернутый в IFFE в порядкедля предотвращения глобального загрязнения

Если все apis принадлежат одному и тому же серверу, вы можете обработать все эти данные на стороне сервера и вернуть один заполненный json.таким образом, ваш сервер проделает небольшую дополнительную работу по созданию этого json, но с другой стороны, вы сделаете только один ajax-запрос вместо 3. Это будет работать быстрее, и вы можете кешировать этот json в течение некоторого времени

Коддля первого решения

(function () {

'use strict';
const studentsUrl = 'api/students';
const teachersUrl = 'api/teachers';
const schoolsUrl = 'api/schools';

let students = null;
let teachers = null;
let schools = null;

var scoolData = {
    schools: null,
    teachers: null,
    students: null
};

$(document).ready(function () {
    getSchools().then(function (schools) {
        scoolData.schools = schools;
        getTeachers().then(function (teachers) {
            scoolData.teachers = teachers;
            $.each(scoolData.teachers, function (key, item) {
                item.school = scoolData.schools[item.schoolId].name;
            });
        });
    });
});

function getSchools() {
    return $.get(schoolsUrl);
}

function getTeachers() {
    return $.get(teachersUrl,
        function (result) {
            scoolData.teachers = result;

            // >>> SHOULD BE SURE, SCHOOLS already loaded!!!
            $.each(teachers, function (key, item) {
                item.school = scoolData.schools[item.schoolId].name;
            });
        });
}
})();
0 голосов
/ 12 октября 2018

Вы можете загружать их асинхронно, но вам нужно дождаться завершения обоих вызовов.

Для этого добавьте return перед вашими вызовами ajax и объедините результаты в функцию готовности (но не в случае успеха).обработчик вызова учителя):

let schoolsPromise = getSchools();
let teachersPromise = getTeachers();
$.when(schoolsPromise, teachersPromise)
  .then((schools, teachers) => {
    $.each(teachers, (key, item) => {
      item.school = schools[item.schoolId].name;
    });
  });
0 голосов
/ 12 октября 2018

Поскольку вам нужны только все доступные результаты, и каждый запрос не зависит от предыдущего, вы можете использовать jQuery.when

let students = null;
let teachers = null;
let schools = null;

$(document).ready(function() {
  $.when(
      getSchools(),
      getTeachers()
  ).done(function(shoolResults, teacherResults) {
      window.schools = shoolResults;
      window.teachers = teacherResults;
      handleTeachers();
      getStudents();
  });


  function getSchools() {
    return $.ajax({
      type: 'GET',
      url: schoolsUrl
    });
  }

  function getTeachers() {
    return $.ajax({
      type: 'GET',
      url: teachersUrl
    });
  }

  function handleTeachers() {
   $.each(teachers, function (key, item) { 
     item.school = schools[item.schoolId].name;
    });
  }
});
0 голосов
/ 12 октября 2018

Я думаю, что вы ищете это.

 getSchools().done(function(data){
      var someId = data.findThatId;
      getTeachers(someId);
 }); 

Вам нужно будет вернуть данные из вызова ajax, чтобы получить data в done.

0 голосов
/ 12 октября 2018

Вызов getTeachers();, когда getSchools(); возврат успешный или завершенный, предпочтительнее успешный, так как завершается, если есть ошибка ..

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...