【问题标题】:Call an async (Promise) function from sync function with Express and Node使用 Express 和 Node 从同步函数中调用异步(Promise)函数
【发布时间】:2019-04-01 15:20:30
【问题描述】:

从基本的 express index.js 文件中,有没有办法从同步函数调用(此处为getData)调用异步函数?

const express = require('express');
const bodyParser = require('body-parser');

// function which calls a Promise
const getData = require('./getAsyncData.js');

const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.get('/authors/:lang', (req, res) => { 

  const lang = req.params.lang; 
  const getResults = getData( lang );
  res.json(getResults);

});

getAsyncData 模块如下所示:

// getAsyncData.js

const getAsyncData = async function () {

  try {

    // Questionable method of recovering the lang parameter here.
    const lang = (arguments.length) ? arguments[0].toUpperCase() : null;

    // Connect to the database
    const connection = await db.connect(true);

    // Get the data
    const {authors, books} = await connection.load();

    // Join results and filter it
    const filtered_results = GetAuhtorsBooks(authors, books, lang);

    // Send it back 
    return filtered_results;

  } catch(e) {

    return null;

  }

};

module.exports = getAsyncData;

但是在index.js 中,对getData 的调用不可避免地发生在getAsyncData 模块内部的调用之前。 getDataundefined。似乎获得结果的唯一方法是在index.js 中做这样的事情:

app.get('/authors/:lang', async (req, res, next) => {

  try {
    const lang = req.params.lang;
    const testResult = await runTests(lang);
    res.json(testResult);

  } catch (e) {

    //this will eventually be handled by the error handling middleware
    next(e) 

  }

});

有没有什么方法可以在 app.get(...) 中不实现异步/等待功能而获得相同的结果?

非常感谢您的任何建议。

【问题讨论】:

  • 不,这是不可能的。 (当然,您可以使用带有承诺回调的 .then() 调用而不是 async/await 语法)。但是你为什么要这样,你有一个可行的解决方案?
  • 您好,Bergi,感谢您的评论。我考试不及格,我想知道为什么。修改上面的 index.js 是不可能的。但是 getAsyncData 模块必须调用 Promise。我尽我所能。
  • 你没有通过测试”是什么意思?错误信息是什么?
  • 我申请了一份工作,他们让我做一个测试,部分答案是:“只将代码放在测试文件中。这是为了运行测试并调用其他带有实际代码的模块,这是大多数语言的标准测试实践。”实际的不可修改代码是调用 app.get(...) 的代码,没有异步功能。在测试中——getAsyncData 模块——我不得不调用一个 Promise 来连接和加载数据。我只是想知道我错在哪里。
  • 了解他们想看什么的唯一方法是问他们,而不是我们。您的解决方案中没有什么是不好的做法,您只是没有满足他们不更改代码的要求。

标签: javascript express asynchronous promise async-await


【解决方案1】:

任何async 函数都会返回一个Promise。 express 支持路由处理程序返回承诺。您可以使用此代码:

const express = require('express');
const bodyParser = require('body-parser');

// function which calls a Promise
const getData = require('./getAsyncData.js');

const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.get('/authors/:lang', async (req, res) => { 

  const lang = req.params.lang; 
  const results = await getData( lang );
  res.json(results);

});

【讨论】:

    【解决方案2】:

    你可以使用.then()的底层API

    app.get('/authors/:lang', (req, res, next) => { 
    
      const lang = req.params.lang; 
      getData( lang )
        .then(getResults => res.json(getResults));
        .catch(next);
    
    });
    

    但是在这一点上,您最好使用async,尤其是当您的代码达到仅获取一个数据点并返回它是不够的,您需要做更多的事情时。

    无论如何,您仍然需要手动调用next()res.error(...),一旦涉及 Promise,您的函数将不再同步抛出或错误。

    【讨论】:

      猜你喜欢
      • 2020-04-20
      • 1970-01-01
      • 2012-07-25
      • 2019-09-02
      • 2021-06-28
      • 2013-07-12
      • 2018-04-09
      • 2020-08-13
      • 2015-03-19
      相关资源
      最近更新 更多