Перейти к содержимому

Promise result как достать

  • автор:

Promise result как достать

Ранее мы рассмотрели, как из функции промиса мы можем передать во вне результат асинхронной операции:

const myPromise = new Promise(function(resolve)< console.log("Выполнение асинхронной операции"); resolve("Привет мир!"); >);

Теперь получим это значение. Для получения результата операции промиса применяется функция then() объекта Promise :

then(onFulfilled, onRejected);

Первый параметр функции — onFulfilled представляет функцию, которая выполняется при успешном завершении промиса и в качестве параметра получает переданные в resolve() данные.

Второй параметр функции — onRejected представляет функцию, которая выполняется при возникновении ошибки и в качестве параметра получает переданные в reject() данные.

Функция then() возвращает также объект Promise .

Так, получим переданные данные:

const myPromise = new Promise(function(resolve)< console.log("Выполнение асинхронной операции"); resolve("Привет мир!"); >); myPromise.then(function(value)< console.log(`Из промиса получены данные: $`); >)

То есть параметр value здесь будет представлять строку «Привет мир!» , которая передается в resolve(«Привет мир!») . В итоге консольный вывод будет выглядеть следующим образом:

Выполнение асинхронной операции Из промиса получены данные: Привет мир!

Для примера вызове несколько промисов, чтобы увидеть асинхронность в деле:

const myPromise3000 = new Promise(function(resolve)< console.log("[myPromise3000] Выполнение асинхронной операции"); setTimeout(()=>, 3000); >); const myPromise1000 = new Promise(function(resolve)< console.log("[myPromise1000] Выполнение асинхронной операции"); setTimeout(()=>, 1000); >); const myPromise2000 = new Promise(function(resolve)< console.log("[myPromise2000] Выполнение асинхронной операции"); setTimeout(()=>, 2000); >); myPromise3000.then((value)=>console.log(value)); myPromise1000.then((value)=>console.log(value)); myPromise2000.then((value)=>console.log(value));

Здесь определены три однотипных промиса. Чтобы каждый из них не выполнялся сразу, они используют функцию setTimeout и устанавливают возвращаемое значение только через несколько секунд. Для разных промисов длительность задержки различается. И в данном случае мы получим следующий консольный вывод:

[myPromise3000] Выполнение асинхронной операции [myPromise1000] Выполнение асинхронной операции [myPromise2000] Выполнение асинхронной операции [myPromise1000] Привет мир! [myPromise2000] Привет мир! [myPromise3000] Привет мир!

Здесь мы видим, что первым начал выполняться промис myPromise3000, однако он же завершился последним, так как для него установлено наибольшее время задержки — 3 секунды. Однако его задержка не помешала выполнению остальных промисов.

При этом нам необязательно вообще передавать в resolve() какое-либо значение. Возможно, асинхронная операция просто выполняется и передает во вне никакого результата.

const x = 4; const y = 8; const myPromise = new Promise(function()< console.log("Выполнение асинхронной операции"); const z = x + y; console.log(`Результат операции: $`) >); myPromise.then();

В данном случае функция в промисе вычисляет сумму чисел x и y и выводит результат на консоль.

Метод Promise.resolve

Иногда требуется просто вернуть из промиса некоторое значение. Для этого можно использовать метод Promise.resolve() . В этот метод передается возвращаемое из промиса значение. Метод Promise.resolve() возвращает объект Promise:

const myPromise = Promise.resolve("Привет мир!"); myPromise.then(value => console.log(value)); // Привет мир!

Определение промиса через функцию

Нередко промис определяется через функцию, которая возвращет объект Promise. Например:

function sum(x, y)< return new Promise(function(resolve)< const result = x + y; resolve(result); >) > sum(3, 5).then(function(value)< console.log("Результат операции:", value);>); sum(25, 4).then(function(value)< console.log("Сумма чисел:", value);>);

Здесь функция sum() принимает два числа и возвращает промис, который инкапсулирует операцию сумму этих чисел. После вычисления сумма чисел передается в resolve() , соответственно мы ее затем можем получить через метод then() . Определение промиса через функцию позволяет нам, с одной стороны, при вызове функции передавать разные значения. А с другой стороны, работать с результатом этой функции как с промисом и настроить при каждом конкретном вызове обработку полученного значения.

Результат работы программы:

Результат операции: 8 Сумма чисел: 29

Однако, что если у нас совпадает принцип обработки полученного из асинхронной функции значения?

sum(3, 5).then(function(value)< console.log("Результат операции:", value);>); sum(25, 4).then(function(value)< console.log("Результат операции:", value);>);

В этом случае логика обработки будет повторяться. Но поскольку метод then() также возвращает объект Promise, то мы можем сделать следующим образом:

function sum(x, y)< return new Promise(function(resolve)< const result = x + y; resolve(result); >).then(function(value)< console.log("Результат операции:", value);>); > sum(3, 5); sum(25, 4);
Гибкая настройка функции

А что, если мы хотим, чтобы у программиста был выбор: если он хочет, то может определить свой обработчик, а если нет, то применяется некоторый обработчик по умолчанию. В этом случае мы можем определить функцию обработчика в качестве параметра функции, а если он не передан, то устанавливать обработчик по умолчанию:

function sum(x, y, func)< // если обработчик не установлен, то устанавливаем обработчик по умолчанию if(func===undefined) func = function(value)< console.log("Результат операции:", value);>; return new Promise(function(resolve)< const result = x + y; resolve(result); >).then(func); > sum(3, 5); sum(25, 4, function(value)< console.log("Сумма:", value);>);

Здесь при первом вызове функции sum() ( sum(3, 5) ) будет срабатывать обработчик по умолчанию. Во втором случае обработчик явным образом передается через третий параметр, соответственно он будет задействован sum(25, 4, function(value)< console.log("Сумма:", value);>)

Промисы

Представьте, что вы известный певец, которого фанаты постоянно донимают расспросами о предстоящем сингле.

Чтобы получить передышку, вы обещаете разослать им сингл, когда он будет выпущен. Вы даёте фанатам список, в который они могут записаться. Они могут оставить там свой e-mail, чтобы получить песню, как только она выйдет. И даже больше: если что-то пойдёт не так, например, в студии будет пожар и песню выпустить не выйдет, они также получат уведомление об этом.

Все счастливы! Вы счастливы, потому что вас больше не донимают фанаты, а фанаты больше не беспокоятся, что пропустят новый сингл.

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

  1. Есть «создающий» код, который делает что-то, что занимает время. Например, загружает данные по сети. В нашей аналогии это – «певец».
  2. Есть «потребляющий» код, который хочет получить результат «создающего» кода, когда он будет готов. Он может быть необходим более чем одной функции. Это – «фанаты».
  3. Promise (по англ. promise , будем называть такой объект «промис») – это специальный объект в JavaScript, который связывает «создающий» и «потребляющий» коды вместе. В терминах нашей аналогии – это «список для подписки». «Создающий» код может выполняться сколько потребуется, чтобы получить результат, а промис делает результат доступным для кода, который подписан на него, когда результат готов.

Аналогия не совсем точна, потому что объект Promise в JavaScript гораздо сложнее простого списка подписок: он обладает дополнительными возможностями и ограничениями. Но для начала и такая аналогия хороша.

Синтаксис создания Promise :

let promise = new Promise(function(resolve, reject) < // функция-исполнитель (executor) // "певец" >);

Функция, переданная в конструкцию new Promise , называется исполнитель (executor). Когда Promise создаётся, она запускается автоматически. Она должна содержать «создающий» код, который когда-нибудь создаст результат. В терминах нашей аналогии: исполнитель – это «певец».

Её аргументы resolve и reject – это колбэки, которые предоставляет сам JavaScript. Наш код – только внутри исполнителя.

Когда он получает результат, сейчас или позже – не важно, он должен вызвать один из этих колбэков:

  • resolve(value) — если работа завершилась успешно, с результатом value .
  • reject(error) — если произошла ошибка, error – объект ошибки.

Итак, исполнитель запускается автоматически, он должен выполнить работу, а затем вызвать resolve или reject .

У объекта promise , возвращаемого конструктором new Promise , есть внутренние свойства:

  • state («состояние») — вначале «pending» («ожидание»), потом меняется на «fulfilled» («выполнено успешно») при вызове resolve или на «rejected» («выполнено с ошибкой») при вызове reject .
  • result («результат») — вначале undefined , далее изменяется на value при вызове resolve(value) или на error при вызове reject(error) .

Так что исполнитель по итогу переводит promise в одно из двух состояний:

Позже мы рассмотрим, как «фанаты» узнают об этих изменениях.

Ниже пример конструктора Promise и простого исполнителя с кодом, дающим результат с задержкой (через setTimeout ):

let promise = new Promise(function(resolve, reject) < // эта функция выполнится автоматически, при вызове new Promise // через 1 секунду сигнализировать, что задача выполнена с результатом "done" setTimeout(() =>resolve("done"), 1000); >);

Мы можем наблюдать две вещи, запустив код выше:

  1. Функция-исполнитель запускается сразу же при вызове new Promise .
  2. Исполнитель получает два аргумента: resolve и reject — это функции, встроенные в JavaScript, поэтому нам не нужно их писать. Нам нужно лишь позаботиться, чтобы исполнитель вызвал одну из них по готовности.

Спустя одну секунду «обработки» исполнитель вызовет resolve(«done») , чтобы передать результат:

Это был пример успешно выполненной задачи, в результате мы получили «успешно выполненный» промис.

А теперь пример, в котором исполнитель сообщит, что задача выполнена с ошибкой:

let promise = new Promise(function(resolve, reject) < // спустя одну секунду будет сообщено, что задача выполнена с ошибкой setTimeout(() =>reject(new Error("Whoops!")), 1000); >);

Подведём промежуточные итоги: исполнитель выполняет задачу (что-то, что обычно требует времени), затем вызывает resolve или reject , чтобы изменить состояние соответствующего Promise .

Промис – и успешный, и отклонённый будем называть «завершённым», в отличие от изначального промиса «в ожидании».

Может быть что-то одно: либо результат, либо ошибка

Исполнитель должен вызвать что-то одно: resolve или reject . Состояние промиса может быть изменено только один раз.

Все последующие вызовы resolve и reject будут проигнорированы:

let promise = new Promise(function(resolve, reject) < resolve("done"); reject(new Error("…")); // игнорируется setTimeout(() =>resolve("…")); // игнорируется >);

Идея в том, что задача, выполняемая исполнителем, может иметь только один итог: результат или ошибку.

Также заметим, что функция resolve / reject ожидает только один аргумент (или ни одного). Все дополнительные аргументы будут проигнорированы.

Вызывайте reject с объектом Error

В случае, если что-то пошло не так, мы должны вызвать reject . Это можно сделать с аргументом любого типа (как и resolve ), но рекомендуется использовать объект Error (или унаследованный от него). Почему так? Скоро нам станет понятно.

Вызов resolve / reject сразу

Обычно исполнитель делает что-то асинхронное и после этого вызывает resolve / reject , то есть через какое-то время. Но это не обязательно, resolve или reject могут быть вызваны сразу:

let promise = new Promise(function(resolve, reject) < // задача, не требующая времени resolve(123); // мгновенно выдаст результат: 123 >);

Это может случиться, например, когда мы начали выполнять какую-то задачу, но тут же увидели, что ранее её уже выполняли, и результат закеширован.

Такая ситуация нормальна. Мы сразу получим успешно завершённый Promise .

Свойства state и result – внутренние

Свойства state и result – это внутренние свойства объекта Promise и мы не имеем к ним прямого доступа. Для обработки результата следует использовать методы .then / .catch / .finally , про них речь пойдёт дальше.

Потребители: then, catch

Объект Promise служит связующим звеном между исполнителем («создающим» кодом или «певцом») и функциями-потребителями («фанатами»), которые получат либо результат, либо ошибку. Функции-потребители могут быть зарегистрированы (подписаны) с помощью методов .then и .catch .

then

Наиболее важный и фундаментальный метод – .then .

promise.then( function(result) < /* обработает успешное выполнение */ >, function(error) < /* обработает ошибку */ >);

Первый аргумент метода .then – функция, которая выполняется, когда промис переходит в состояние «выполнен успешно», и получает результат.

Второй аргумент .then – функция, которая выполняется, когда промис переходит в состояние «выполнен с ошибкой», и получает ошибку.

Например, вот реакция на успешно выполненный промис:

let promise = new Promise(function(resolve, reject) < setTimeout(() =>resolve("done!"), 1000); >); // resolve запустит первую функцию, переданную в .then promise.then( result => alert(result), // выведет "done!" через одну секунду error => alert(error) // не будет запущена );

Выполнилась первая функция.

А в случае ошибки в промисе – выполнится вторая:

let promise = new Promise(function(resolve, reject) < setTimeout(() =>reject(new Error("Whoops!")), 1000); >); // reject запустит вторую функцию, переданную в .then promise.then( result => alert(result), // не будет запущена error => alert(error) // выведет "Error: Whoops!" спустя одну секунду );

Если мы заинтересованы только в результате успешного выполнения задачи, то в then можно передать только одну функцию:

let promise = new Promise(resolve => < setTimeout(() =>resolve("done!"), 1000); >); promise.then(alert); // выведет "done!" спустя одну секунду

catch

Если мы хотели бы только обработать ошибку, то можно использовать null в качестве первого аргумента: .then(null, errorHandlingFunction) . Или можно воспользоваться методом .catch(errorHandlingFunction) , который сделает то же самое:

let promise = new Promise((resolve, reject) => < setTimeout(() =>reject(new Error("Ошибка!")), 1000); >); // .catch(f) это то же самое, что promise.then(null, f) promise.catch(alert); // выведет "Error: Ошибка!" спустя одну секунду

Вызов .catch(f) – это сокращённый, «укороченный» вариант .then(null, f) .

Очистка: finally

По аналогии с блоком finally из обычного try <. >catch <. >, у промисов также есть метод finally .

Вызов .finally(f) похож на .then(f, f) , в том смысле, что f выполнится в любом случае, когда промис завершится: успешно или с ошибкой.

Идея finally состоит в том, чтобы настроить обработчик для выполнения очистки/доведения после завершения предыдущих операций.

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

Думайте об этом как о завершении вечеринки. Независимо от того, была ли вечеринка хорошей или плохой, сколько на ней было друзей, нам все равно нужно (или, по крайней мере, мы должны) сделать уборку после нее.

Код может выглядеть следующим образом:

new Promise((resolve, reject) => < /* сделать что-то, что займёт время, и после вызвать resolve или может reject */ >) // выполнится, когда промис завершится, независимо от того, успешно или нет .finally(() => остановить индикатор загрузки) // таким образом, индикатор загрузки всегда останавливается, прежде чем мы продолжим .then(result => показать результат, err => показать ошибку)

Обратите внимание, что finally(f) – это не совсем псевдоним then(f,f) , как можно было подумать.

Есть важные различия:

  1. Обработчик, вызываемый из finally , не имеет аргументов. В finally мы не знаем, как был завершён промис. И это нормально, потому что обычно наша задача – выполнить «общие» завершающие процедуры. Пожалуйста, взгляните на приведенный выше пример: как вы можете видеть, обработчик finally не имеет аргументов, а результат promise обрабатывается в следующем обработчике.
  2. Обработчик finally «пропускает» результат или ошибку дальше, к последующим обработчикам. Например, здесь результат проходит через finally к then :

new Promise((resolve, reject) => < setTimeout(() =>resolve("value"), 2000); >) .finally(() => alert("Промис завершён")) // срабатывает первым .then(result => alert(result)); // 

Как вы можете видеть, значение возвращаемое первым промисом, передается через finally к следующему then . Это очень удобно, потому что finally не предназначен для обработки результата промиса. Как уже было сказано, это место для проведения общей очистки, независимо от того, каков был результат. А здесь ошибка из промиса проходит через finally к catch :

new Promise((resolve, reject) => < throw new Error("error"); >) .finally(() => alert("Промис завершён")) // срабатывает первым .catch(err => alert(err)); // 
  • Обработчик finally не получает результат предыдущего обработчика (у него нет аргументов). Вместо этого этот результат передается следующему подходящему обработчику.
  • Если обработчик finally возвращает что-то, это игнорируется.
  • Когда finally выдает ошибку, выполнение переходит к ближайшему обработчику ошибок.

Эти функции полезны и заставляют все работать правильно, если мы используем finally так, как предполагается: для общих процедур очистки.

На завершённых промисах обработчики запускаются сразу

Если промис в состоянии ожидания, обработчики в .then/catch/finally будут ждать его.

Иногда может случиться так, что промис уже выполнен, когда мы добавляем к нему обработчик.

В таком случае эти обработчики просто запускаются немедленно:

// при создании промиса он сразу переводится в состояние "успешно завершён" let promise = new Promise(resolve => resolve("готово!")); promise.then(alert); // готово! (выведется сразу)

Пример: loadScript

Теперь рассмотрим несколько практических примеров того, как промисы могут облегчить нам написание асинхронного кода.

У нас есть функция loadScript для загрузки скрипта из предыдущей главы.

Давайте вспомним, как выглядел вариант с колбэками:

function loadScript(src, callback) < let script = document.createElement('script'); script.src = src; script.onload = () =>callback(null, script); script.onerror = () => callback(new Error(`Ошибка загрузки скрипта $`)); document.head.append(script); >

Теперь перепишем её, используя Promise .

Новой функции loadScript более не нужен аргумент callback . Вместо этого она будет создавать и возвращать объект Promise , который перейдет в состояние «успешно завершён», когда загрузка закончится. Внешний код может добавлять обработчики («подписчиков»), используя .then :

function loadScript(src) < return new Promise(function(resolve, reject) < let script = document.createElement('script'); script.src = src; script.onload = () =>resolve(script); script.onerror = () => reject(new Error(`Ошибка загрузки скрипта $`)); document.head.append(script); >); >
let promise = loadScript("https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"); promise.then( script => alert(`$ загружен!`), error => alert(`Ошибка: $`) ); promise.then(script => alert('Ещё один обработчик. '));

Сразу заметно несколько преимуществ перед подходом с использованием колбэков:

Промисы Колбэки
Промисы позволяют делать вещи в естественном порядке. Сперва мы запускаем loadScript(script) , и затем ( .then ) мы пишем, что делать с результатом. У нас должна быть функция callback на момент вызова loadScript(script, callback) . Другими словами, нам нужно знать что делать с результатом до того, как вызовется loadScript .
Мы можем вызывать .then у Promise столько раз, сколько захотим. Каждый раз мы добавляем нового «фаната», новую функцию-подписчика в «список подписок». Больше об этом в следующей главе: Цепочка промисов. Колбэк может быть только один.

Таким образом, промисы позволяют улучшить порядок кода и дают нам гибкость. Но это далеко не всё. Мы узнаем ещё много полезного в последующих главах.

promise js как вытащить данные [дубликат]

введите сюда описание изображения

получаю такой промис, как мне вытащить из него данные и занести в переменную? код:

async function fetchDate(key, zone) < const result = await fetch(`http://api.timezonedb.com/v2.1/get-time-zone?$&format=json&by=zone&zone=$`); return result; > let result = fetchDate(key, newYorkZone); let newYorktime = result.then(json => json.json()); console.log(newYorktime) 

Отслеживать
14k 2 2 золотых знака 11 11 серебряных знаков 20 20 бронзовых знаков
задан 12 сен 2020 в 10:52
25 1 1 серебряный знак 4 4 бронзовых знака
Может помочь: ru.stackoverflow.com/a/554337/321883
12 сен 2020 в 12:40

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Как вариант, можно написать одельную функцию по выполнению каких либо задач, например, для вывода в консоль значения время Нью Йорка:

const setTimeNewYork = (time) => < console.log(time) //либо другие операции >result.then(response => < data = response.json() data.then((value) =>< setTimeNewYork(value[key]) console.log(value[key])//value представлено как Object console.log(Object.keys(value))//просмотр всех ключей в виде массива console.log(Object.values(value))//просмотр всех значений в виде массива >) >); 

Отслеживать
51.6k 201 201 золотой знак 63 63 серебряных знака 245 245 бронзовых знаков
ответ дан 7 июл 2022 в 17:24
masquarade masquarade

    Важное на Мете
Связанные
Похожие

Дизайн сайта / логотип © 2024 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2024.1.3.2953

Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.

Как из promise достать значение js

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

// Создаём промис const promise = new Promise((resolve, reject) =>  // Промис возвращает строку 'success!' resolve('success!'); >); // Добавляем к промису then и передаём функцию promise.then((result) =>  // внутри функции получаем результат промиса console.log(result); // => success! >); 

Либо можно использовать async await :

// Создаём промис const promise = new Promise((resolve, reject) =>  // Промис возвращает строку 'success!' resolve('success!'); >); // Объявляем асинхронную функцию const func = async () =>  // внутри функции получаем результат промиса const result = await promise(); console.log(result); // => success! >; // Не забываем вызвать функцию func(); 

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

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