【问题标题】:How to use response from three different API calls in node js at one time如何一次在节点 js 中使用来自三个不同 API 调用的响应
【发布时间】:2018-07-22 01:26:52
【问题描述】:

我正在尝试使用 nodeJS 创建一个 Web 应用程序,但由于 nodeJS 的异步特性,我被卡住了。

我有三个不同的环境,根据来自 html 表单的用户输入,我应该检查用户是否存在于所选环境中。

html 将有 3 个复选框,用户可以选择任意数量的环境。

if(Dev_Environmnet){
    getUserDatafromEnvironment(user,environment, function(callback1)){
        if(callback1.error){
            // User Does Not Exist Or credentials are wrong
        }
        else{
            //get User API 
        }

    });
}
if(PVS_Environmnet){
    getUserDatafromEnvironment(user,environment, function(callback1)){
        if(callback1.error){
            // User Does Not Exist Or credentials are wrong
        }
        else{
            //get User API 
        }

    });
}
if(Prod_Environmnet){
    getUserDatafromEnvironment(user,environment, function(callback1)){
        if(callback1.error){
            // User Does Not Exist Or credentials are wrong
        }
        else{
            //get User API 
        }

    });
}

一旦完成,我需要回调的结果将其打印到另一个 HTML 页面。这是我需要在下一页显示的内容

DEV - API key gdeuysgdsgddiudgqwywdgAguiegdhsiw
pVS - user does not exist or credentials are wrong
Prod - APYI Key ugehdfiyugfugew%$%$udisfiuhygyig

我无法一次获得所有这些值。有人可以帮我吗?

【问题讨论】:

  • 将您的调用转换为getUserDatafromEnvironment,以便它返回一个承诺,然后使用 Promise.all(array) 一次处理所有结果。
  • 您好,感谢您的回复。你能告诉我怎么做吗..?我的意思是使用代码。
  • Promise.all() 不好,因为它需要所有三种机制来解决。 AFAICS OP 希望 任何一个或多个 成功。也就是说,如果函数被包装以便它们总是以成功/失败结果解析,而不是在仍然可以工作的失败时生成reject
  • @Alnitak 您能否详细说明您在这里所说的内容。
  • @Alnitak Promise.all() 非常适合用于此。您只需要处理每个提供程序中的错误,并将 null 或类似的内容返回到 Promise.all() 数组中的 Promise。

标签: javascript html node.js api


【解决方案1】:

首先,您可以包装您的getUserDatafromEnvironment,使其返回Promise

function getUserDatafromEnvironmentP(flag, user, environment) {
    if (!flag) return Promise.resolve(undefined);  // method not selected

    return new Promise(function(resolve) {
        getUserDatafromEnvironment(user, environment, function(callback) {
            resolve(!callback.error);
        })
     });
}

然后您可以调用您的三个方法并将它们传递给Promise.all(),这将等到所有三个都完成并告诉您结果:

let p1 = getUserDatafromEnvironmentP(Dev_Environmnet, user, environmnet);
let p2 = getUserDatafromEnvironmentP(PVS_Environmnet, user, environmnet);
let p3 = getUserDatafromEnvironmentP(Prod_Environmnet, user, environmnet);

let result = Promise.all([p1, p2, p3]).then(
    function(results) {
        // results[0 .. 2] will contain the three results
        // undefined for "not used", false for "failed", true for "ok"
        .. continue with processing here
    })
);

// you can't do anything useful here because the above code is async

注意:通常我不赞成使用resolve 来表示失败,但在这种情况下,由于随后使用Promise.all(),这似乎是合适的。

【讨论】:

  • 非常感谢您的帮助。它现在工作。 :)
【解决方案2】:

根据你的伪代码,类似这样。

// I assume that you need special functions to get the information
// from different providers.

function getUserFromPVS(user) {
  return new Promise( (resolve, reject) => {
    // special code to get user from PVS
    return resolve(userdata);
  });
}
function getUserFromDev(user) {
  return new Promise( (resolve, reject) => {
    // special code to get user from Dev
    return resolve(userdata);
  });
}
function getUserFromProd(user) {
  return new Promise( (resolve, reject) => {
    // special code to get user from Prod
    return resolve(userdata);
  });
}

// Converted the call to getUserDatafromEnvironment so it is a promise.
function getUserData(flagSelected, user, environment, req) {
  return new Promise( (resolve, reject) => {
    if (!flagSelected) return resolve(null); // Returns null if not selected
    getUserDatafromEnvironment(user,environment, (cb) => {
      if (cb.error) {
        return resolve(null); // Return NULL instead of rejecting.
      } else {
        // Call to promise that return user information
        // I assume you need different functions for
        // each provider
        return resolve( req(user) )
      }
    })

  });
}
Promise.all([
  getUserData( PVS_Environmnet, user, environment, getUserFromPVS ),
  getUserData( Dev_Environmnet, user, environment, getUserFromDev ),
  getUserData( Prod_Environmnet, user, environment, getUserFromProd ),
]).then( (results) => {
  // results[0] has result from Dev or is null
  // results[1] has result from PVS or is null
  // results[2] has result from Prod or is null
}).catch(
  (error) => console.error(error)
)

【讨论】:

  • 您没有确保requests(因此results)实际上包含三个元素。你也有很多重复的代码。
  • @Alnitak 不正确(不再),
【解决方案3】:

您应该在以前的回调中保留对其他检查的调用:

checkOne(someArgs, (callback) => {
    let checkOneResult = true;
    if (callback.error)
        checkOneResult = false;
    checkTwo(someArgs, (callback) => {
        let checkTwoResult = true;
        if (callback.error)
            checkTwoResult = false;

        //here I got result from both checks:
        console.log(checkOneResult);
        console.log(checkTwoResult);
    });
});

【讨论】:

  • 这对我不起作用,因为用户决定从哪些环境中获取用户 API。如果用户只选择 prod 环境,我只需要 prod 的这个结果。并且输出应该只显示 Prod API Key hgveufygsiyefgaesdiu86538
  • 这也序列化三个访问而不是同时运行所有它们
【解决方案4】:

如果您的意思是“知道所有 3 个异步操作何时完成”,不确定您所说的“立即获取它们”是什么意思,那么有几种方法可以做到这一点,建议您考虑将异步方法转换为 Promise (How do I convert an existing callback API to promises?) 并使用 Promise.all 或查看使用 async 和 await。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-23
    • 2011-05-12
    • 2021-11-07
    • 1970-01-01
    • 2021-06-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多