Как вернуть данные из обещания

Мне нужно получить response.data из обещания, чтобы оно могло быть возвращено включающей функцией. Я знаю, что, вероятно, я не могу сделать это так, как я это написал, из-за нормальной области видимости JavaScript. Есть ли способ сделать это?

Console.log в #1 выдает правильные данные. console.log #2 всегда выдает 'a';

function addSiteParentId(nodeId) {   
    var theParentId = 'a';
    var parentId = relationsManagerResource.GetParentId(nodeId)
                        .then(function(response){                               
                            theParentId = response.data;
                            console.log(theParentId);  // #1
                        });
    console.log(theParentId);  // #2
    return theParentId;
}

Любые указатели будут оценены.

4 ответа

Решение

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

Вместо этого вы, скорее всего, захотите вернуть само обещание. Тогда любая функция, которой нужен ее результат, может вызвать .then() на обещание, и результат будет там, когда обещание было выполнено.

Вот ресурс из HTML5Rocks, который проходит жизненный цикл обещания, и как его вывод разрешается асинхронно:
http://www.html5rocks.com/en/tutorials/es6/promises/

Мне также не нравится использовать функцию для обработки свойства, которое разрешается снова и снова в каждом контроллере и сервисе. Кажется я не одинок:D

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

Во-первых, напишите результат в свойство вашего сервиса:

app.factory('your_factory',function(){
   var theParentIdResult = null;
   var factoryReturn = {  
          theParentId: theParentIdResult,
          addSiteParentId : addSiteParentId
   }
    return factoryReturn;
    function addSiteParentId(nodeId) {   
         var theParentId = 'a';
         var parentId = relationsManagerResource.GetParentId(nodeId)
                    .then(function(response){                               
                        factoryReturn.theParentIdResult = response.data;
                        console.log(theParentId);  // #1
           });                    
    }        
})

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

  • Использовать разрешение в методе маршрутизатора:

    разрешения: { parentId: function (your_factory){ your_factory.addSiteParentId(); } }

затем в контроллере и других службах, используемых на вашем маршрутизаторе, просто вызовите your_factory.theParentId, чтобы получить вашу собственность. Обратитесь сюда для получения дополнительной информации: http://odetocode.com/blogs/scott/archive/2014/05/20/using-resolve-in-angularjs-routes.aspx

  • Используйте метод приложения "run" для разрешения вашего сервиса.

    app.run (функция (your_factory){your_factory.addSiteParentId();})

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

Выбор ваших способов зависит от вашего контекста, зависит от области действия вашей переменной и частоты чтения вашей переменной.

Один из способов вернуть данные по обещанию - это

const addSiteParentId = (nodeId) => {   
    const  data = { theParentId: "" }
    relationsManagerResource.GetParentId(nodeId).then((response)=> Object.assign(data, data.theParentId, response.data)/* #1 */);
    return data.theParentId;
}
// Object.assign do this magic
console.log("theParentId:", addSiteParentId(nodeId))

Object.assign: https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

Вы должны вернуть обещание вместо переменной. Так что в вашей функции просто вернуть:

return relationsManagerResource.GetParentId(nodeId)

А позже разрешите возвращенное обещание. Или вы можете сделать другую отсрочку и решить theParentId с этим.

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