节点API等待外部数据

时间:2018-10-04 19:39:22

标签: javascript json node.js express promise

我正在尝试构建服务器,该服务器将从外部API提取数据并将其返回到标准端点localhost:3000 / v1 / api /。问题在于获取数据大约需要2秒钟,而我总是最终渲染一个空对象。

我有2个文件。第一个data.js是从使用axios的外部api中获取数据的样子,

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 :(得分:2)

在第二个文件(服务器)中,您这样写:

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

好吧,我怀疑基于第一个文件,数据构造函数正在调用“异步”功能:

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);
            })
        });
}

但这只是一个例子,也许您应该总体上检查代码的结构以适应它。

在简历中,只要不执行表示http请求永不响应的res.send()函数,您就始终等待诺言响应。