Node.js - Попытка встроить функцию обратного вызова в функцию обратного вызова. - PullRequest
0 голосов
/ 17 апреля 2020

У меня есть следующий код

const request = require('request');

var url = "https://api.warframe.market/v1/items";

var options = {
  json: true
};
var item_urls;


request(url, options, (error, res, body) => {
  if (error) {
    return console.log(error)
  };

  if (!error && res.statusCode == 200) {

    item_urls = body.payload.items;

    console.log("done");

  };
});

Он извлекает файл JSON, анализирует его и сохраняет в items_urls. Работает нормально без проблем. Примечание: я запускаю этот код непосредственно в терминале REPL узла через мою IDE, чтобы я мог его отладить. После выполнения вышесказанного я набираю item_urls на терминале и выводит результаты. В случае, если вам интересно, почему я так сделал, эта переменная будет использоваться позже в другой функции, выходящей за рамки этого поста. Я делаю это так, потому что это единственный способ сохранить выходные данные из «запроса» в переменную (объясняется далее).

У меня есть две проблемы:

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

const request = require('request');

var url = "https://api.warframe.market/v1/items";

var options = {
  json: true
};
var item_urls;

function test() {
request(url, options, (error, res, body) => {
  if (error) {
    return console.log(error)
  };

  if (!error && res.statusCode == 200) {

    item_urls = body.payload.items;

    console.log("done");

  };
});
}


Как вы можете видеть, я только обернул часть кода "request" в функцию с именем test. Когда я вызываю эту функцию test(), она делает то же, что и выше, и выводит данные в item_urls. У меня проблема в том, что я хочу, чтобы функция возвращала данные, а не выводила их в эту переменную. Когда я запускаю test() в REPL, он говорит undefined. Это ожидается, потому что функция ничего не возвращает. Например, я хотел бы сохранить выходные данные в x, когда я запускаю var x = test(), но опять же при просмотре x он говорит неопределенный. Я думаю, что проблема связана с обратными вызовами, которые я еще не полностью понял.

Вторая проблема заключается в том, что я хочу, чтобы items_url внутри функции, как мне сказали, это наилучшая практика.

Вот мой последний код, в котором я пытаюсь вернуть данные :

const request = require('request');

var url = "https://api.warframe.market/v1/items";

var options = {
  json: true
};


function test() {
    var item_urls;
request(url, options, (error, res, body) => {
  if (error) {
    return console.log(error)
  };

  if (!error && res.statusCode == 200) {

    item_urls = body.payload.items;

    console.log("done");

  };
});
return item_urls;
}


Я перемещаю объявление items_url var внутри функции, затем использую return items_url, чтобы вернуть его. Если я тогда снова запускаю x = test(), он все равно говорит неопределенное. Я пытался переместить оператор return в разные блоки кода, но он никогда не работал. Что я делаю неправильно? Мне нужно, чтобы вернуть данные.

1 Ответ

1 голос
/ 17 апреля 2020

Есть много способов решить эту проблему. Лучше понять программирование asyn c.

const request = require("request");

var url = "https://api.warframe.market/v1/items";

var options = {
  json: true,
};

function test() {
  var item_urls;
  request(url, options, (error, res, body) => {
    if (error) {
      return console.log(error);
    }
    if (!error && res.statusCode == 200) {
      item_urls = body.payload.items;
      console.log("done");
    }
  });
  // return item_urls;  // WIll return, before even getting data
}

// SOL 1
// USING CALLBACK
function test(cb) {
  request(url, options, (error, res, body) => {
    if (!error && res.statusCode == 200) {
      cb(body.payload.items);
    }
  });
}
test((urls) => {
  console.log(urls);
});

// SOL 2
// USING PROMISE
function test() {
  return new Promise((r, rr) => {
    request(url, options, (error, res, body) => {
      if (error) {
        return rr(error);
      }
      if (!error && res.statusCode == 200) {
        return r(body.payload.items);
      }
    });
  });
}
test().then((urls) => {
  console.log(urls);
});

const {promisify} = require("util")
const pr = promisify(request)
// SOL 3
// USING ASYNC- AWAIT
async function test() {
  const res = await pr(url, options)
  return res.body.payload.items
}
test().then((urls) => {
  console.log(urls);
});
...