简体   繁体   English

节点API等待外部数据

[英]Node API to wait for external data

I'm trying to build server which will fetch data from external API and return them to the standard endpoint localhost:3000/v1/api/. 我正在尝试构建服务器,该服务器将从外部API提取数据并将其返回到标准端点localhost:3000 / v1 / api /。 The problem is that it takes around 2 sec to get the data and instead I always end up rendering an empty object. 问题是获取数据大约需要2秒钟,而我总是最终渲染一个空对象。

I have 2 files. 我有2个档案。 The first one data.js is to fetch the data from the external api which uses axios and looks like that: 第一个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;

And the second file is the server itself so I can render the response to the browser. 第二个文件是服务器本身,因此我可以将响应呈现给浏览器。

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

I am always getting an empty object before the data is even fetched from the external API. 在从外部API提取数据之前,我总是会得到一个空对象。 I thought that Promise will help but nope still the same issue. 我认为Promise会有所帮助,但不会出现同样的问题。 Any ideas how this should be done in a right way? 任何想法如何正确地做到这一点?

in the second file (the server), you wrote this: 在第二个文件(服务器)中,您这样写:

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

Ok, i suspect based on the first file, the Data constructor is calling to a "async" function: 好的,我怀疑基于第一个文件,数据构造函数正在调用“异步”函数:

this.checkIfPageExists();

This function is calling to axios.get, I presume this is a promise and the execution of the constructor is continuing before the response of checkIfPageExists, basically in the second file when you writing: 该函数正在调用axios.get,我认为这是一个承诺,并且构造函数的执行在checkIfPageExists响应之前继续进行,基本上是在编写时在第二个文件中:

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

Is executing resolve without a response. 正在执行解析而没有响应。

You need to rewrite this logic for wait to promise resolve/reject. 您需要重写此逻辑,以等待承诺解决/拒绝。

For example: 例如:

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;

In the second file, changing: 在第二个文件中,更改:

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

But is only an example, maybe you should review the structure of the code in general to adapt it. 但这只是一个示例,也许您应该总体上检查代码的结构以适应它。

In resume, you always wait to promises responses, as long as you do not execute the res.send() function of express the http request never response. 在简历中,只要不执行表示http请求永不响应的res.send()函数,就始终等待诺言响应。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM