简体   繁体   English

带有 express、node、ejs 的 Axios 请求

[英]Axios requests with express, node, ejs

I am working on a site using Express.js, node.js, Axios, and ejs.我在一个使用 Express.js、node.js、Axios 和 ejs 的网站上工作。 I am making REST calls to a Oracle SQL REST services using Axios.我正在使用 Axios 对 Oracle SQL REST 服务进行 REST 调用。 I am having trouble working with Promises or Async/Await.我在使用 Promise 或 Async/Await 时遇到问题。 I could use some guidance, if possible.如果可能的话,我可以使用一些指导。

I have a repository layer to interface with the Oracle DB.我有一个与 Oracle DB 交互的存储库层。 For example:例如:

dataaccess.js数据访问.js

const axios = require('axios');

exports.IsManufacturerCategory = function (categoryId) {
    axios.get(`DB ADDRESS ${categoryId}`)
        .then(response => {
            console.error('GET IsManufacturerCategory categoryId = ' + categoryId);
            console.error('Response = ' + JSON.stringify(response.data));

            return (response.data);
        })
        .catch(rej => {
            console.error('ERROR IsManufacturerCategory categoryId = ' + categoryId);
            console.error('ERR = \n' + rej.data);
            return (rej.data);
        });
}

Which is called in my middleware.在我的中间件中调用。 When I call var isManufacturerCat = exports.IsManufacturerCategory(categoryId);当我调用var isManufacturerCat = exports.IsManufacturerCategory(categoryId); it is undefined.它是未定义的。 I am attempting to use the data retrieved from the Axios call to return a ejs view to my router, which I can provide if needed.我正在尝试使用从 Axios 调用中检索到的数据将 ejs 视图返回到我的路由器,如果需要,我可以提供。

category.js类别.js

var isManufacturerCat = exports.IsManufacturerCategory(categoryId);
if (isManufacturerCat) {
    var models = dataaccess.GetCategorySubCategories(categoryId);
    return ("manufacturers", {
        data: {
            Canonical: cononical, 
            Category: category, 
            IsAManufacturerCategory: iAManufacturerCat, 
            Models: models
        }
    });
}

I am open to any advice in my project structure, usage of Promises, Async/Await, etc.我对我的项目结构、Promises 的使用、Async/Await 等方面的任何建议持开放态度。

Thank you in advance.先感谢您。

EDIT编辑

After working with some of the answers given, I have made some progress but I am having issues with layers of async calls.在处理了一些给出的答案后,我取得了一些进展,但我在异步调用层方面遇到了问题。 I end up getting into a spot where I need to await a call, but I am in a function that I am not able/do not want to do so (ie my router).我最终进入了一个需要await呼叫的地方,但我处于我无法/不想这样做的功能中(即我的路由器)。

indexMiddleware.js indexMiddleware.js

exports.getRedirectURL = async function (fullOrigionalpath) {

    if (fullOrigionalpath.split('.').length == 1 || fullOrigionalpath.indexOf(".aspx") != -1) {
        if (fullOrigionalpath.indexOf(".aspx") != -1) { 
            //some string stuff to get url

        }
        else if (fullOrigionalpath.indexOf("/solutions/") != -1) {
            if (!fullOrigionalpath.match("/solutions/$")) {
                if (fullOrigionalpath.indexOf("/t-") != -1) {
                    //some stuff
                }
                else {
                    var solPart = fullOrigionalpath.split("/solutions/");
                    solPart = solPart.filter(function (e) { return e });

                    if (solPart.length > 0) {
                        var solParts = solPart[solPart.length - 1].split("/");
                        solParts = solParts.filter(function (e) { return e });
                        if (solParts.length == 1) {
                            waitForRespose = true;

                            const isASolutionCategory = await dataaccess.isASolutionCategory(solParts[0]); // returns void

                            if (isASolutionCategory != undefined && isASolutionCategory.length > 0 && isASolutionCategory[0].Count == 1) {
                                 // set redirecturl   
                            }
                        }
                        else {
                            redirecturl = "/solutions/solutiontemplate";
                        }
                    }
                }
            }
        }
        else if (URL STUFF) {
            // finally if none of the above fit into url condition then verify current url with Category URL or product url into database and if that matches then redirect to proper internal URL
            if (fullOrigionalpath.lastIndexOf('/') == (fullOrigionalpath.length - 1)) {
                fullOrigionalpath = fullOrigionalpath.substring(0, fullOrigionalpath.lastIndexOf('/'));
            }

            waitForRespose = true;

            const originalURL = await exports.getOriginalUrl(fullOrigionalpath); //returns string
            redirecturl = originalURL;
            return redirecturl;
        }
    }

    if (!waitForRespose) {
        return redirecturl; 
    }
}

exports.getOriginalUrl = async function (friendlyUrl) {
    var originalUrl = '';
    var urlParts = friendlyUrl.split('/');
    urlParts = urlParts.filter(function (e) { return e });
    if (urlParts.length > 0) {
        var skuID = urlParts[urlParts.length - 1];

        const parts = await dataaccess.getFriendlyUrlParts(skuID); //returns void
        console.log("Inside GetOriginalUrl (index.js middleware) FriendlyUrlParts: " + parts);//undefined

        if (parts != undefined && parts != null && parts.length > 0) {
            //some stuff
        }
        else {
            // verify whether it's category URL then return the category local URL
            console.log('Getting CategoryLocalUrl');
            const categoryLocalUrl = await dataaccess.getCategoryLocalUrl(friendlyUrl); // returns void
            console.log('CategoryLocalUrl Gotten ' + JSON.stringify(categoryLocalUrl)); //undefined
            if (categoryLocalUrl != undefined && categoryLocalUrl.length > 0) {
                //set originalUrl
                return originalUrl;
            }

        }
    }
    else { return ''; }
}

index.js router index.js 路由器

router.use(function (req, res, next) {
   //bunch of stuff
   index.getRedirectURL(url)
      .then(res => {
        req.url = res;
      })
      .catch(error => {
        console.error(error);
      })
      .finally(final => {
        next();
      });
}

I am getting undefined in my console.log s after the await s.await之后,我在console.log变得undefined I'm not really sure what I'm doing I guess.我不确定我在做什么,我猜。

Let's start with dataaccess.js.让我们从 dataaccess.js 开始。 Basically, you're exporting a function that's doing async work, but the function isn't async.基本上,您正在导出一个执行异步工作的函数,但该函数不是异步的。 Most people want to be able to utilize async/await, so rather than have IsManufacturerCategory accept a callback function, it would better to have the function return a promise.大多数人都希望能够使用 async/await,因此与其让IsManufacturerCategory接受回调函数,不如让该函数返回一个承诺。 The easiest way to do that is to make the function an async function.最简单的方法是使函数成为异步函数。 Async functions return promises which are resolved/rejected more easily than by returning an explicit promise.异步函数返回比通过返回显式承诺更容易解决/拒绝的承诺。 Here's how that could be rewritten:下面是如何重写:

const axios = require('axios');

exports.IsManufacturerCategory = async function (categoryId) {
  try {
    const response = await axios.get(`DB ADDRESS ${categoryId}`);

    console.log('GET IsManufacturerCategory categoryId = ' + categoryId);
    console.log('Response = ' + JSON.stringify(response.data));
  } catch (err) {
    console.error('ERROR IsManufacturerCategory categoryId = ' + categoryId);
    console.error('ERR = \n' + rej.data);

    throw err;
  }
}

Note that I'm using console.error only for errors.请注意,我仅将console.error用于错误。 Because you wanted to log some error related details, I used a try/catch statement.因为您想记录一些与错误相关的详细信息,所以我使用了 try/catch 语句。 If you didn't care about doing that, the function could be simplified to this:如果您不关心这样做,该功能可以简化为:

const axios = require('axios');

exports.IsManufacturerCategory = async function (categoryId) {
    const response = await axios.get(`DB ADDRESS ${categoryId}`);

    console.log('GET IsManufacturerCategory categoryId = ' + categoryId);
    console.log('Response = ' + JSON.stringify(response.data));
}

This is because async functions automatically swallow errors and treat them as rejections - so the promise returned by IsManufacturerCategory would be rejected.这是因为异步函数会自动吞下错误并将它们视为拒绝 - 因此IsManufacturerCategory返回的承诺将被拒绝。 Similarly, when an async function returns a value, the promise is resolved with the value returned.类似地,当异步函数返回一个值时,promise 将使用返回的值进行解析。

Moving on to category.js... This looks strange because you're accessing IsManufacturerCategory from the exports of that module when I think you mean to access it from the import of the dataaccess module, right?转到category.js...这看起来很奇怪,因为当我认为您的意思是从dataaccess模块​​的导入访问它时,您正在从该模块的导出访问IsManufacturerCategory ,对吗?

Inside this function, you should put any async work in an async function so that you can use await with function that return promises.在此函数中,您应该将任何异步工作放在异步函数中,以便您可以将 await 与返回承诺的函数一起使用。 Here's how it could be rewritten:下面是如何重写它:

const dataaccess = require('dataccess.js');

async function validateManufacturerCat(categoryId) {
  const isManufacturerCat = await dataaccess.IsManufacturerCategory(categoryId);

  if (isManufacturerCat) {
    const models = await dataaccess.GetCategorySubCategories(categoryId);

    return ({
      manufacturers: {
        data: {
          Canonical: cononical, 
          Category: category, 
          IsAManufacturerCategory: iAManufacturerCat, 
          Models: models
        }
      }
    });
  }
}

validateManufacturerCat(categoryId)
  .then(res => {
    console.log(res);
  })
  .catch(err => {
    console.error(err);
  });

A couple notes:一些注意事项:

  1. I changed the return value in the if statement to be a single value.我将if语句中的返回值更改为单个值。 You should try to always return a single value when working with promises and async/await (since you can only resolve/return one value).在使用 promise 和 async/await 时,您应该尝试始终返回一个值(因为您只能解析/返回一个值)。
  2. I see lots of functions starting with capital letters.我看到很多以大写字母开头的函数。 There's a convention in JavaScript where functions with capital letters are constructor functions (meant to be invoked with the new keyword). JavaScript 中有一个约定,其中带有大写字母的函数是构造函数(意味着使用new关键字调用)。

Here is a working example.这是一个工作示例。 Note that you need a callback function to get the data when it is available from the promise请注意,您需要一个回调函数来获取可从承诺中获得的数据

//client.js
const axios = require("axios")


    exports.IsManufacturerCategory = function (url, callback) { 
       axios.get(url)
         .then(response=>
            {
                 callback(response.data);
            })
            .catch(error=>{
                callback( error);
            })
    };


    //app.js
   const client = require('./client');

    function process(data) {

        console.log(data)
    }    
     client.IsManufacturerCategory("http://localhost:3000/persons",process);

documentation文件

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

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