2015-11-12 2 views
1

Я очень новичок в программировании (3 месяца), и у меня возникают проблемы с тем, как узел обрабатывает асинхронные функции (я думаю).Проблема с узлом асинхронного запроса GET с использованием обещаний

У меня есть объект класса Merchant с методом «addMenu», который делает запрос GET для меню из внешнего API, а затем обновляет продавца, установив объект merchant.data.menu (который по умолчанию равен null) новое меню, которое мы только что получили.

код в вопросе:

this.addMenu = function(currentMerchant) { 
    var id = currentMerchant.id; 

    function getMenu(id) { 
    var deferred = Q.defer(); 
    var url = 'https://api.delivery.com/merchant/'+id+'/menu?client_id=xyz'; 

    request.get(url, function(error, response, body) { 
     if(error) { 
     console.log("Something went wrong with menu GET request: Status Code: " + response.statusCode); 
     deferred.reject(new Error(error)); 
     } else if(!error && response.statusCode == 200) { 
     menuObj = JSON.parse(body); 
     deferred.resolve(menuObj); 
     }   
    }); 

    return deferred.promise; 
    }; 

    this.data.menu = getMenu(id).then(function(currentMenu) { 
    return currentMenu; 
    }); 

    console.log(this.data.menu); 
}; 

При входе (this.data.menu), я получаю "{состояние: 'в ожидании'}." Я могу сделать setTimeout и заставить работать, но разве это не побеждает целую цель обещаний? Я застрял в этой общей проблеме в течение нескольких дней - вникал в обратные вызовы, задержки, обещания и т. Д., Чтобы решить эту проблему, но думаю, что, возможно, мне не хватает чего-то более фундаментального в моем мышлении.

Спасибо!

Изменить, чтобы добавить:

Ну в конце концов я понял, что реальная суть моей проблемы была невозможность доступа this.data.menu изнутри обратного вызова/обещания, которые приводят меня делать все виды странных вещей и попытки вернуть их в это. переменная и т. д.

Просто прочитайте «var that = this;» трюк, чтобы получить доступ к классу, который сделал все мои обратные вызовы и обещания попытками работать нормально и сделать sooo гораздо больше смысла в моей голове. И теперь я знаю намного больше о обещаниях, которые я когда-либо планировал в качестве побочной выгоды. Спасибо за помощь людям!

+1

Обещания не магически делают синхронный асинхронный код. Они могут только упростить наше лечение асинхронности. – Bergi

ответ

1

Возвращение от метода then по-прежнему является обещанием и поэтому не будет выполнено. Это сложная парадигма, чтобы сначала окунуться в голову. (когда-либо играл порталы? :))

Я думаю, что вы хотите сделать что-то вроде этого

getMenu(id).then(function(currentMenu) { 
    this.data.menu = currentMenu; 
}); 

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

Любой код за пределами этого не гарантированно будет запущен после того, как обещание вернуться (именно поэтому вы получаете, что выход консоли)

+0

Посмотрите, что имеет большой смысл и как я изначально был настроен. Но у меня нет доступа к 'this.data.menu' из функции обратной связи функции .then. Наверное, здесь я застрял. И если я попытаюсь временно назначить его переменной в методе addMenu, а затем назначить это «this.data.menu», она будет успешно удалять ее там, если я добавлю задержку, чтобы вернуться к квадрату ... Спасибо за вашу помощь. – greenleaf

+0

Кажется, что с этим вы сейчас сталкиваетесь, это объем этого в обратном вызове. Есть много сообщений, которые объяснят это лучше, чем я мог. Это довольно распространенная проблема, которую некоторые люди не рекомендуют использовать, а другие не согласны. Это зависит от вас, чтобы вы задумали. Вот пример сообщения http://weblogs.asp.net/dwahlin/working-with-the-javascript-this-keyword – ScottG

+0

Спасибо ScottG, это была моя проблема ...будет изучать теории «этого» использования – greenleaf

-1

Вы также можете использовать Bluebird для promisify запрос и сделать что-то вроде этого :

var Promise = require('bluebird'); 

var getRequest = Promise.promisify(require('http').get); 

this.addMenu = function(currentMerchant) { 
    var id = currentMerchant.id; 

    function getMenu(id) { 
    var deferred = Q.defer(); 
    var url = 'https://api.delivery.com/merchant/'+id+'/menu?client_id=xyz'; 

    return getRequest(url); 
    } 

    this.data.menu = getMenu(id) 
         .then(function(response) { 
         return JSON.parse(response.body); 
         }) 
         .catch(function (err){ 
         console.log("Something went wrong with menu GET request: " + err); 
         }); 

    console.log(this.data.menu); 
}; 
+0

OP уже использует Q. – Mathletics

+0

Да, так что Q и пойти с библиотекой, которая позволяет вам пролонгировать обратные вызовы. Его проблема заключается не в отсутствии понимания обещаний, а в смешении обещаний с обратными вызовами. – tacotuesday

+0

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

Смежные вопросы