0

Вопрос Как сделать return из callback-а?

например, есть функция

getParams(["ArrayOfParamNames"], function(CallbackResult){
    //code
});

Мне нужно достать этот CallbackResult

типа

    function getResult(){
        getParams(["Param1","Param2"], function(res){
            //Код в колбэке
        });
        return res; // ретёрним тот самый res, который объявляли в getParams(["Param1","Param2"], function(res)...);
    }
var x = getResult()

2 Answers2

3

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

function getResult(arrOfParamNames) {
  return new Promise((resolve, reject) => {
    return getParams(arrOfParamNames, function(CallbackResult){
      //code
      //при благоприятных условиях выполнения функции вызываем resolve
      resolve(CallbackResult)

      //иначе reject
      //отсюда выполнение попадет в catch
    });
  });
}



getResult(["Param1","Param2"])
  .then(res => {
    //при успешном выполнении
    //что то делаем с res
  })
  .catch(err => {
    //при неуспешном выполнении
    //что то делаем с err
  })

Подробнее почитайте тут и тут.

2

у меня вот так работает:

function getGeoName(message) {
        request({
            url: url,
            json: true
        }, function (error, response, body) {
            if (!error && response.statusCode === 200) {
                if (body.geonames && body.geonames.length > 0) {
                    return weather("CityName");
                }else return message.addText('Я не знаю такого города, попробуйте написать город по английски').send();
            } else return message.addText('Я не знаю такого города, попробуйте написать город по английски').send();
        })
    };
function weather(city2) {
}

У вас должно работать так:

function getResult(){
    getParams(["Param1","Param2"], function(res){
       return result(res);
    });
}
function result(){
}

Другой вариант:

var global;
setTimeout(function () {
    function getResult() {
        getParams(["Param1", "Param2"], function (res) {
            global = res;
        });
    }
}, 8000);

Async await пример:

function serialAsyncMap(collection, fn) {
        let global = [];
        let promise = Promise.resolve();
        getParams(["Param1", "Param2"], function (res) {
            promise = promise.then(() => fn(res)).then(result => global.push(result));
        });
    return promise.then(() => global);
}
  • А если перед getParams поставить return? – Данил Чугаев Mar 15 '18 at 06:49
  • может просто из за асинхронности не успевает вернуть – Paulo Berezini Mar 15 '18 at 06:53
  • @PauloBerezini Не помогло, либо я не так написал, либо что-то еще. Можно ли какой-нибудь глобальной переменной присвоить значение этого res? – Андрей Григорьев Mar 15 '18 at 06:59
  • @ДанилЧугаев Не получится – Андрей Григорьев Mar 15 '18 at 07:01
  • Да, можно через глобальную переменную, но учтите, что вы не знаете, когда вызовется callback. Это зависит от специфики устройства функции, куда вы передаете этот callback. Обычно, если вам нужно что-то сделать с результатами работы callback, это делается внутри самого callback вызовом еще одной функции, как в ответе. В итоге получаем гирлянды callback, за что и ругают иногда JS-код – wirtwelt Mar 15 '18 at 07:03
  • В глобальную переменную я бы не стал класть – Paulo Berezini Mar 15 '18 at 07:05
  • @wirtwelt Я как раз сделал так, чтоб мне было не важно, когда колбэк вызывается Мне нужно просто время от времени (сэтИнтервалом) получать эти параметры, а потом, в другое время их использовать, а так как функция достаточно долгая - вызывать ее именно во время использования параметров задерживает выполнение – Андрей Григорьев Mar 15 '18 at 07:06
  • @PauloBerezini мне как раз нужно в глобальную, см коммент выше – Андрей Григорьев Mar 15 '18 at 07:06
  • Делайте глобальную переменную. Пишите из callback туда значение. В интервале читайте значение и работайте с ним, если не NULL например, и сбрасывайте значение в NULL. Тогда вы точно будете знать, что это актуальное значение, записанное из callback. Однако это похоже на костыль, вам не кажется? Если вам надо просто на новое значение делать работу - вызов функции из callback гораздо приятнее выглядит, имхо – wirtwelt Mar 15 '18 at 07:08
  • 1
    посмотрите 3 пример-костыль – Paulo Berezini Mar 15 '18 at 07:11
  • посмотрите 4 пример – Paulo Berezini Mar 15 '18 at 07:27