Возвращенный ответ unirest в node.js не определен

Я работаю над ботом facebook, но я никоим образом не являюсь разработчиком node.js, я использую его впервые, потому что я хотел немного выйти из своей зоны комфорта.

Это моя функция запроса

function requestExc() {
    var resDictionary = {} 
    unirest.get("http://openapi.ro/api/exchange/" + queryDict["code"] + ".json")
    .query({"date" : queryDict["date"]})
    .end(function(res) {
        if (res.error) {
            console.log('GET error', res.error)
        } else {
            console.log('GET response', res.body)
            resDictionary["rate"] = res.body["rate"]
            resDictionary["date"] = res.body["date"]
        }
    })

    console.log("resDictionary IS " + resDictionary)
    ///prints resDictionary IS [object Object]
    return resDictionary
}

поэтому я пытаюсь получить результат

var response = requestExc()
if (response !== null) {
    respondToSender(response, sender)
}

а потом действовать соответственно

function respondToSender(res, sender) {
    console.log("RES IS " + res)
    //prints RES IS [object Object]
  if (res["rate"] === null) {
        //do stuff
  }
}

но когда переменная попадает в responseToSender, она всегда не определена.

 TypeError: Cannot read property 'rate' of undefined

Я также пробовал с Json.parse(), но это то же самое.


person Alex Bartiş    schedule 24.06.2016    source источник
comment
С одной стороны, вам, вероятно, следует использовать if (response) вместо if (response !== null); с другой стороны, это не объясняет, почему он всегда не определен.   -  person YakovL    schedule 24.06.2016
comment
Спасибо, обновлю!   -  person Alex Bartiş    schedule 24.06.2016


Ответы (2)


Хорошо, проблема в том, что unirest (как и многие модули node.js) работает асинхронно, что означает, что ваш код, скорее всего, выполняется в следующем порядке:

var response = requestExc() // request is sent first, ok
if (response !== null) {    // this is done second
    respondToSender(response, sender)
}
                            // the response arrived third, when it is not needed

Поэтому, чтобы иметь дело с такими вещами, вы должны использовать метод callbacks/end. См. пример здесь:

unirest.post('http://mockbin.com/request')
.query('name=nijiko')
.query({
  pet: 'spot'
})
.end(function (response) {
  console.log(response); // this is where you should use respondToSender
});

console.log(response); запускается только тогда, когда пришел ответ, а это то, что вы хотите.

person YakovL    schedule 24.06.2016
comment
Я сделал это. Вот откуда я начал, и это было то же самое. Пробовал вернуться в .end { return response.body }, и это было то же самое. Вот почему я попытался создать словарь снаружи и вернуть его только в конце. - person Alex Bartiş; 24.06.2016
comment
Понимаю. Чтобы убедиться, что это проблема, вы также можете войти response в main и посмотреть порядок этих сообщений журнала (вероятно, это будет первый неопределенный, второй объект). Но что вы имеете в виду то же самое для этого случая? Был ли response неопределенным в end, когда он был объектом в requestExc? - person YakovL; 24.06.2016
comment
Другой способ. Это был объект при печати или доступе в .end, но неопределенный при доступе к значению из функции requestExc. - person Alex Bartiş; 24.06.2016
comment
@AlexBartiş Вот как вы должны с этим работать: используйте requestExc внутри .end. Вы пробовали это? - person YakovL; 24.06.2016
comment
requestExc — это метод, выполняющий запрос. Это вошло бы в бесконечный цикл. - person Alex Bartiş; 24.06.2016
comment
@AlexBartiş извините, я имел в виду respondToSender - person YakovL; 24.06.2016
comment
Да, но это не соответствует моей потребности. Мне нужно запустить этот запрос несколько раз, НО после того, как я сделаю первый запрос, мне нужно что-то сделать, а после того, как все остальные запросы будут выполнены, мне нужно сделать что-то еще. - person Alex Bartiş; 24.06.2016
comment
@AlexBartiş Ну, это возможно при асинхронной обработке. См. эту статью, чтобы получить представление (или, скорее, полный инструмент): zackehh. ком/ . Это тоже может представлять интерес: stackoverflow.com/questions /17607280/ И, наконец, еще одна статья об асинхронной природе Node.js: code.tutsplus.com/tutorials/ Да, чтобы использовать Node.js, вам нужно выйти из своей зоны комфорта :) - person YakovL; 24.06.2016

Кто-то из Reddit научил меня, как добавить обратный вызов, и теперь он работает так, как я хочу. Полный код:

// GET a resource
function requestExc(callback) {
    unirest.get("http://openapi.ro/api/exchange/" + queryDict["code"] + ".json")
    .query({"date" : queryDict["date"]})
    .end(function(res) {
        if (res.error) {
            console.log('GET error', res.error)
            callback(res.error, null)
        } else {
            console.log('GET response', res.body)
            callback(null, res.body)
        }
    })
}

и я называю это

var response = requestExc(function(error, res) {
            console.log("date array is " + dateArray)
            if (error === null) {
                respondToSender(res["rate"], res["date"], sender, queryDict)
            } else {
                sendTextMessage(sender, "Imi pare rau, dar am intimpinat o problema in comunicarea cu BNR")
            }
        })
person Alex Bartiş    schedule 25.06.2016
comment
Да, это то, что я имел в виду, respondToSender в приведенном ниже коде — это то же самое, что и обратный вызов. надеюсь ответ был хотя бы полезен - person YakovL; 25.06.2016
comment
@YakovL да, но на самом деле мне было непонятно, как использовать обратный вызов. Но теперь, когда я это вижу, это действительно просто и работает так же, как наши обработчики завершения в swift. Спасибо за помощь! - person Alex Bartiş; 26.06.2016