Меню

Применение промисов, и установка состояния промисов для тестов

05.07.2018 - java script, ЯП

Consuming promises

Мы уже рассматривали асинхронные вызовы на колбэках. Теперь мы переделали функции обернув содержимое в промисы. А сейчас рассмотрим как нам получить данные из промисов.

console.log('Before');
getUser(1, (user) => {
  getRepositories(user.gitHubUsername, (repos) => {
    getCommits(repos[0], (commits) => {
      console.log(commits);
    })
  })
});
console.log('After');

function getUser(id) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log('Reading a user from a database...');
      resolve({
        id: id,
        gitHubUsername: 'mosh'
      });
    }, 2000);
  });
}

function getRepositories(username) {
  return new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log('Calling GitHub API...');
    resolve(['repo1', 'repo2', 'repo3']);
  }, 2000);
});
}

function getCommits(repo) {
  return new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log('Calling GitHub API...');
    resolve(['commit']);
  }, 2000);

})
}

Вызываем getUser и передаем ему 1 в качестве аргумента. Этот getUser возвращает промис. Мы уже знаем, что каждый промис имеет два метода then и catch. Итак, мы вызываем then. Какой в нашем случае результат операции? Результат объект user. Итак мы передаем функцию с аргументом user. Теперь нам нужно получить результат функции getPepositories, которая в качестве аргумента получает полученный из прошлого промиса объект user.

Если мы в then в колбэке возвращаем промис, то можем использовать цепочку then. Т.е. предыдущий resolve выдал нам репозитории пользователя, мы передаем его в следующий then и получаем комиты с помощью функции getCommits, которая, тоже возвращает промис. И best practice является, что в каждом вызове промисов, или цепочки, вы должны указывать catch метод, для отлова ошибок в любом из звеньев цепочки.

getUser(1)
  .then(user => getRepositories(user.gitHubUsername))
  .then(repos => getCommits(repos[0]))
  .then(commits => console.log(`Commits: `, commits));
  .catch(err => console.error(`Error:`, error))

Creating settled promises

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

Допустим вам нужно симулировать ситуацию, когда запрос к сервису завершился успешно. В вашем юнит тесте вы хотите создать промис, который уже был зарезолвлен. Итак, для этого нам нужно вызвать статический метод resolve класса Promise. И он вернет резолвнутый промис. Мы можем передать в него значение, если захотим. Затем мы можем вызвать then и делать свои темные делишки.

const p = Promise.resolve({id: 1});
p.then(result => console.log(result));

Аналогично, иногда вам нужно создать промис, который уже реджекнут. В этому случае мы указываем метод reject и передаем в него объект ошибки.

const z = Promise.reject(new Error('Some error'));
z.then(null, err => console.error("Обшибка", err))
    .catch(err => console.error('I catched: ', err))

При reject лучше использовать родной Error объект, потому что он будет включать callstack. Если передать обычную строку, мы не увидим этого в стэке вызовов.

Когда реджектите — всегда используйте объект Error

Метки: , , ,

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *