Использование переменной вне области действия функции обратного вызова в Node.js / Express.js

Я использую библиотеку node-geocoder в express js, которая имеет следующий код:

var NodeGeocoder = require('node-geocoder');

var options = {
  provider: 'google',

  // Optional depending on the providers
  httpAdapter: 'https', // Default
  apiKey: 'YOUR_API_KEY', // for Mapquest, OpenCage, Google Premier
  formatter: null         // 'gpx', 'string', ...
};

var geocoder = NodeGeocoder(options);

// Using callback
geocoder.geocode('29 champs elysée paris', function(err, res) {
  console.info(res);
});

Переменная ответа (res) в функции обратного вызова метода геокодирования содержит объект со свойствами местоположения, такими как широта и долгота. Ссылка на этот пакет: здесь

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

Как новичок, я попытался просто вернуть объект и сохранить его в такой переменной:

var object = geocoder.geocode('29 champs elysée paris', function(err, res) {

   return res;

});

Это не работает, так как оно находится в обратном вызове и не возвращается в фактическом методе геокодирования.

Один из способов решить эту проблему - вызвать функцию из обратного вызова. Мой ответ ниже

edkeveked 02.04.2018 19:39
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
1
108
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Вы можете использовать ответ своей функции вне обратного вызова, вызвав другую функцию.

geocoder.geocode('29 champs elysée paris', function(err, res) {
  if (!err){
    // call a function if there is no error
    console.info(res);
    myFunction();
  }
 });

function myFunction(){
 //do your processing here
}

I don't want to keep the rest of the code within that callback function.

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

Итак, вы пишете свою функцию (или функции) как обычно:

function handleInfo(info) {
    doSomethingWithInfo(info);
    doSomethignElse(info);
    // ...
}
// ...

... а затем вызовите эти функции, когда у вас есть данные:

geocoder.geocode('29 champs elysée paris', function(err, info) {
  if (err) {
      // Handle error
  } else {
      handleInfo(info);
  }
});
Ответ принят как подходящий

Не напрямую, но есть несколько способов приблизиться к этому.

Один из них - сделать ваш обратный вызов определенной функцией и использовать ее как обратный вызов:

const doSomething = (err, res) => { /* do something */ }

geocoder.geocode('abc', doSomething);

На самом деле не сильно отличается, но может сделать его немного чище.

Вы также можете «обещать» функцию, чтобы она возвращала Promise. Что-то вроде этого поможет:

const geocodePromise = (path) => new Promise((resolve, reject) => {
    geocoder.geocode(path, (err, res) => err ? reject(err) : resolve(res));
});

geocodePromise('abc')
  .then(res => { /* do something */ })
  .catch(err => { /* do something */ });

Наконец, если вы используете Babel для транспиляции (или Node версии 7.6.0 или выше, у которой он изначально есть), вы можете использовать async и await. Используя ту же обещанную версию функции, что и выше, вам придется заключить свой основной код в функцию async. Обычно для этого я использую анонимную функцию с автоматическим вызовом:

(async () => {
  try {
    const res = await geocodePromise(path);

    /* do something with res */
  } catch (err) {
    /* do something with err */
  }
})();

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

geocode уже может вернуть обещание, не нужно его заново оборачивать. Если вас не волнует ошибка и вы просто хотите получить данные о местоположении ответа. Ты можешь сделать это

var locationData = geocoder.geocode('29 champs elysée paris').then( function(res){
    return res;
});

Другие вопросы по теме