Node API для ожидания внешних данных - PullRequest
0 голосов
/ 04 октября 2018

Я пытаюсь создать сервер, который будет извлекать данные из внешнего API и возвращать их на стандартную конечную точку localhost: 3000 / v1 / api /.Проблема в том, что получение данных занимает около 2 секунд, и вместо этого я всегда получаю пустой объект.

У меня есть 2 файла.Первый data.js - это выборка данных из внешнего API, который использует axios и выглядит так:

const axios = require('axios');

class Data {
  constructor() {
    this.array = [];
    this.checkIfPageExists();
  }

  get array() {
    if (this.array.length > 0) {
      return this.array;
    }
  }

  checkIfPageExists() {
    axios.get('http://external.api.address/status')
    .then(response => {
      if (response.status === 200) {
         this.fetchData();
      }
     })
  }

  fetchData() {
    axios.get('http://external.api.address/data')
    .then(response => {
      if (response.data.length > 0) {
         this.array = response.data;
      }
     })
  }
}

module.exports = Data;

А второй файл - это сам сервер, поэтому я могу обработать ответ в браузере.

const express = require('express');
const cors = require('cors');
const Data = require('./data');

const port = 8000;
const app = express();

const middleware = (req, res, next) => {
    const myPromise = () => {
        return new Promise(function(resolve, reject) {
            let data = new Data();
            resolve(data.array);
        });
    }

    let promise = myPromise();

    promise.then((data) => {
        if (data) {
            console.log(data)
            res.data = data;
            next();
        }
    })

}

class Server {
    constructor() {
        this.initCORS();
        this.initMiddleware();
        this.initRoutes();
        this.start();
    }

    start() {
        app.listen(port, () => {
            console.log("Listening on port: " + port);
        })
    }

    initCORS() {
        app.use(cors());
    }

    initMiddleware() {
        app.use(middleware);
    }

    initRoutes() {
        app.get("/", (req, res) => {
            res.send(JSON.stringify(res.data, null, '\t'));
        });
    }

}

new Server();

Я всегда получаю пустой объект еще до того, как данные извлекаются из внешнего API.Я думал, что Promise поможет, но нет, все та же проблема.Есть идеи, как это сделать правильно?

1 Ответ

0 голосов
/ 04 октября 2018

во втором файле (сервере), вы написали это:

return new Promise(function(resolve, reject) {
        let data = new Data();
        resolve(data.array);
    });

Хорошо, я подозреваю, что на основании первого файла конструктор данных вызывает функцию "async":

this.checkIfPageExists();

Эта функция вызывает axios.get, я предполагаю, что это обещание, и выполнение конструктора продолжается до ответа checkIfPageExists, в основном во втором файле, когда вы пишете:

let data = new Data();
resolve(data.array);

Выполняет разрешение без ответа.

Вам нужно переписать эту логику для ожидания, чтобы пообещать разрешение / отклонение.

Например:

const axios = require('axios');
class Data {
  constructor() {
    this.array = [];
    // --- FIX: No check in this line ---
  }

  get array() {
    if (this.array.length > 0) {
      return this.array;
    }
  }

  checkIfPageExists() {
    // return a promise:
    return new Promise((resolve, reject) => {
      axios.get('http://external.api.address/status')
      .then(response => {
        if (response.status === 200) {
           this.fetchData().then(()=>{ resolve(); });
        }
      })
     });
  }

  fetchData() {
    // return the promise:
    return axios.get('http://external.api.address/data')
    .then(response => {
      if (response.data.length > 0) {
         this.array = response.data;
      }
     })
  }
}

module.exports = Data;

Ввторой файл, изменяющийся:

const myPromise = () => {
        return new Promise(function(resolve, reject) {
            let data = new Data();
            data.checkIfPageExists().then(()=>{
              resolve(data.array);
            })
        });
}

Но это только пример, возможно, вам следует пересмотреть структуру кода в целом, чтобы адаптировать его.

В резюме вы всегда ждете ответов на обещания, если вы не выполняете функцию res.send () для экспресс-запроса http, никогда не отвечаете.

...