NodeJS 等待 HTTP 请求

Posted

技术标签:

【中文标题】NodeJS 等待 HTTP 请求【英文标题】:NodeJS wait for HTTP request 【发布时间】:2017-07-30 19:08:51 【问题描述】:

我想编写一个从 API 请求令牌的应用程序。只要此令牌不可用,我就不想继续应用程序的其余部分。所以它必须像一个同步的 HTTP 请求。

我的目标是创建一个执行请求然后返回令牌的函数,例如:

var token=getToken();  //After this function has finished
makeRequest(token);   //I want this function to be executed

我该怎么做?

【问题讨论】:

相关:***.com/questions/6048504/… 【参考方案1】:

它根本不想同步。拥抱回调的力量:

function getToken(callback) 
    //get the token here
    callback(token);
;

getToken(function(token)
    makeRequest(token);
);

这确保在 getToken 完成之前不会执行 makeRequest。

【讨论】:

所以这意味着在回调函数中我的整个代码必须被执行? @Chaos_:是的,异步代码总是如此(尽管有 await 这样的语法糖)。 如果你愿意。它有助于模块化执行不同任务的函数,因为您可能会再次使用它们并且您不应该重复自己。如果您之前使用过其他同步语言,例如 php,那么新的语法风格可能需要一些时间来适应。请记住,在您的第一个示例中,在 getToken() 完成之前,var token 是未定义的,并且 makeRequest 将立即执行,无论是否(很可能没有)getToken 完成。 你不知道这个答案有多棒。网络上的所有其他解释都如此宏大和令人困惑。这很简单,而且非常有帮助。如果我可以投票两次,我会的。谢谢!【参考方案2】:

我的目标是创建一个执行请求然后返回令牌的函数

你不能创建一个函数来返回一个它没有立即返回的值。你只能返回一个承诺。

然后在代码的其他部分中,您可以使用 then 处理程序等待 promise 完成,也可以使用类似:

var token = await getToken();

在 async function 内部等待该值可用,但前提是 getToken() 函数返回一个承诺。

例如,使用request-promise 模块会是这样的:

var rp = require('request-promise');
function getToken() 
    // this returns a promise:
    return rp('http://www.example.com/some/path');
)

然后是其他一些功能:

function otherFunction() 
    getToken().then(token => 
        // you have your token here
    ).catch(err => 
        // you have some error
    );

或者,async function 类似这样:

async function someFunction() 
    try 
        var token = await getToken();
        // you have your token here
     catch (err) 
        // you have some error
    

见:https://www.npmjs.com/package/request-promise

请注意,async functionawait 是在 ECMAScript 2017 草案 (ECMA-262) 中定义的,截至 2017 年 3 月撰写本文时尚未最终确定(将在 2017 年 6 月)。

但它已经在 Node v7.6 中可用(如果你使用 --harmony 标志,它从 v7.0 开始可用)。与 Node 版本的兼容性见:

http://node.green/#ES2017-features-async-functions

如果您希望旧 Node 版本具有类似的功能,但语法略有不同,您可以使用 Bluebird 中的 co 或 Promise.coroutine 等模块。

【讨论】:

request-promise is now deprecated【参考方案3】:

您可以使用 javascript Promise 或 Promise 库,例如 async

通过 JavaScript 承诺:

new Promise((resolve, reject) => 
   resolve(getToken());
).then(token =>
    //do you rest of the work
    makeRequest(token);
).catch(err =>
   console.error(err)
)

【讨论】:

【参考方案4】:

您可以使用 ES6 的生成器功能。您可以关注article 以获得更深入的概念。但基本上你可以使用生成器和承诺来完成这项工作。我正在使用bluebird 来承诺和管理生成器。

您的代码应该没问题,如下例所示。

const Promise = require('bluebird');

function getToken()
  return new Promise(resolve=>
           //Do request do get the token, then call resolve(token).
         )


function makeRequest(token)
   return new Promise(resolve=>
     //Do request do get whatever you whant passing the token, then call resolve(result).
   )


function* doAsyncLikeSync()
  const token= yield getToken();  //After this function has finished
  const result = yield makeRequest(token);   //I want this function to be executed
  return result;


Promise.coroutine(doAsyncLikeSync)()
  .then(result => 
    //Do something with the result
  )

【讨论】:

以上是关于NodeJS 等待 HTTP 请求的主要内容,如果未能解决你的问题,请参考以下文章

如何在一个请求中等待,直到另一个请求完成 nodeJS 中相同功能的执行

当事件循环等待数据库操作时,如何处理对 nodejs 服务器的传入请求

为啥等待不适用于节点请求模块?

Sails.js 控制器等待异步服务方法

等待所有 HTTP 请求在 XCode UI 测试中完成?

HTTP请求超时时间导致的请求长时间等待