javascript обработка нескольких мьютексов обратного вызова - PullRequest
0 голосов
/ 14 марта 2020

Я довольно новичок в javascript. Допустим, у меня есть следующий код.

let sources =["http://localhost:3001/resources/black_bish",""http://localhost:3001/resources/white_bish""]
let loaded_images=0
sources.forEach(ele = > {
    let img = new Image()
    img.src = ele
    img.onload = function () {
        loaded_images=++
    }
})

Здесь у меня возник вопрос о Javascript и параллелизме. Разве нельзя вызывать 2 обратных вызова одновременно с работой с потоками? Здесь, не будет ли условия гонки? Если бы я должен был выполнить действие, отличное от «loaded_images = ++ », есть ли какое-либо состояние гонки, например, манипулирование структурой данных, о котором я должен беспокоиться?

Спасибо

1 Ответ

0 голосов
/ 14 марта 2020

Один из способов - вернуть Promise для каждого загружаемого вами изображения. Это обещание будет разрешать , или с точки зрения мирян: продолжаться, когда выполняется правильное условие, всякий раз, когда изображения были загружены. Это похоже на оператор return, но вместо завершения функции вы переходите к следующему шагу.

Promise.all - это метод конструктора обещаний, который принимает массив обещаний. Когда все обещания в массиве были заполнены (то есть вызван resolve), сделайте что-нибудь со значениями всех обещаний.

const loadImage = (source) => new Promise(resolve => {
  let img = new Image();
  img.onload = function() {
    resolve(img);
  };
  img.src = source;
});

const whenAllImagesAreLoaded = (...sources) => Promise.all(
  sources.map(source => loadImage(source));
);

whenAllImagesAreLoaded('image-1.jpg', 'image-2.jpg').then((images) => {
  images.forEach(image => {
    console.log(image, ' is loaded');
  });
});

Другой пример также с обещаниями в сочетании с синтаксисом async / await, который останавливает выполнение до тех пор, пока обещание, которое вы ожидаете, не будет выполнено.

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

async function loadImagesSequentially(...sources) {
  for (const source of sources) {
    let image = await loadImage(source);
    console.log(image, ' is loaded');
  }
}

Оба метода дают вам лучший контроль над обработкой условий гонки или полностью устраняют их. Я бы посоветовал вам практиковаться как можно больше с обещаниями. Это очень мощный инструмент в вашем JavaScript наборе инструментов.

Если у вас есть какие-либо вопросы, пожалуйста, дайте мне знать.

...