NodeJS - 使用嵌套API调用循环

时间:2017-08-22 19:21:06

标签: javascript node.js

您好我是NodeJs的新手,我正在努力找到让这一系列事件发挥作用的最佳方法。我必须做两个API调用才能获得我需要的所有信息。第一个API调用只是一个ID列表,然后第二个API调用我传递ID以获取每个对象的其余信息。

然而,使用下面的方法,我不知道什么时候完成。请有人帮助我。

#lib/MyApp/guardian_serializer.ex
defmodule MyApp.GuardianSerializer do
  @behaviour Guardian.Serializer
  alias MyApp.Repo
  alias MyApp.User

  def for_token(user = %User{}), do: {:ok, "User:#{user.id}"}
  def for_token(_), do: {:error, "Unknown resource type"}

  def from_token("User:" <> id), do: {:ok, Repo.get(User, id)}
  def from_token(_), do: {:error, "Unknown resource type"}
end

5 个答案:

答案 0 :(得分:2)

你可以让你的findMore方法返回一个promise,这样你就可以将一个数组传递给Promise.all并在所有promises完成后处理.then。

function getData() { 
        var options = {
        method: 'GET',
        uri: 'https://api.call1.com',
            qs: {
                access_token: _accessToken,
            }
        };

        request(options).then(function(apires){
           console.log("complete 1");
            var obj = JSON.parse(apires);
            var promises = [];

            obj.data.forEach(function(entry) {        
                promises.push(findMore(entry.id));
            });

            return Promise.all(promises);
        })
        .then(function (response) {
             // Here response is an array with all the responses
             // from your calls to findMore
         })
 }


 function findMore(id) {
        var options = {
        method: 'GET',
        uri: 'https://api.call2.com',
            qs: {
                access_token: _accessToken,
            }
        };
        return request(options);
 }

答案 1 :(得分:1)

要考虑的几件事情:

如果您关心承诺的命运,请务必将其归还

在您的情况下,findMore不会从request返回承诺,因此getData无法跟踪该承诺的解决(或拒绝)。

您可以使用Promise.all跟踪多个承诺的分辨率。

  

Promise.all()方法返回一个Promise,它在iterable参数中的所有promise都已解析或者iterable参数不包含promise时解析。它拒绝承认拒绝的第一个承诺。

让我们在你的例子中使用这些:

function getData() { 
    var options = {
        method: 'GET',
        uri: 'https://api.call1.com',
        qs: {
            access_token: _accessToken,
        }
    };

    return request(options)
        .then(function(apires){
            var obj = JSON.parse(apires);
            var findMorePromises = obj.data.map(function(entry) {        
                return findMore(entry.id)
            });
            return Promise.all(findMorePromises);
        })
}

function findMore(id) {
    var options = {
        method: 'GET',
        uri: 'https://api.call2.com',
        qs: {
            access_token: _accessToken,
        }
    };

    return request(options)
        .then(function(apires){
           return JSON.parse(apires);
        })
}

我已经使用map构建了promises数组,但您也可以使用foreach并推入类似于您的示例代码的数组。< / p>

确保你处理任何承诺的拒绝(通过catch)也是一种很好的做法,但我认为这不属于这个问题的范围。

答案 2 :(得分:0)

您想使用Promise.all。

首先,首先需要一系列承诺。在每个循环中,将findMore设置为变量,并使其返回promise。然后有一行你在哪里做Promise.all(promiseArr).then(function(){console.log(“done)})

您的代码看起来像这样

print '@totalCount'
print '------------'
print @totalCount

Promise.all的基本思想是,只有在数组中的所有承诺都已解决或任何承诺失败时才会执行。您可以阅读更多相关信息here

答案 3 :(得分:0)

您需要使用Promise.all并行运行所有异步请求。此外,您必须返回findMoregetData的结果(它们是承诺)。

function getData() { 
  var options = {...};
  return request(options)
    .then(function(apires) {
      console.log("complete 1");
      var obj = JSON.parse(apires);
      var ops = obj.data.map(function(entry) {
        return findMore(entry.id);
      });
      return Promise.all(ops);
}

function findMore(id) {
  var options = {...};
  return request(options)
    .then(function(apires) {
      console.log("complete 2");
      return JSON.parse(apires);
    });
}

getData()
  .then(data => console.log(data))
  .catch(err => console.log(err));

如果您可以使用ES7,可以使用async / await编写:

let getData = async () => { 
  let options = {...};
  let res = awit request(options);
  let ops = res.data.map(entry => findMore(entry.id));
  let data = await Promise.all(ops);
  return data;
};

let findMore = async (id) => {
  let options = {...};
  let apires = awit request(options);
  return JSON.parse(apires);
};

答案 4 :(得分:0)

编辑:正如其他人所提到的,在这种情况下使用Promise.all()可能是更好的解决方案。

如果您愿意使用jQuery(JavaScript库),那么您可以使用.ajaxStop()事件处理程序并指定您自己的函数。示例代码:

$(document).ajaxStop(function(){
    alert("All AJAX requests are completed.");
});

您需要包含jQuery模块。 Node.js的说明是:

  1. 通过npm安装模块:

    npm install jquery
    
  2. 然后使用“require”在JavaScript代码中使用jQuery(需要一个包含文档的窗口,但Node中没有这样的“窗口”,因此您可以使用jsdom模拟一个),请参阅{{3有关详细信息:

    require("jsdom").env("", function(err, window) {
        if (err) {
            console.error(err);
            return;
        }
    
        var $ = require("jquery")(window);
    });
    
  3. 如果您想坚持使用纯JavaScript方法,则需要创建自己的“模块”来跟踪AJAX请求。在此模块中,您可以跟踪有多少待处理请求,并在终止后删除它们。有关详细信息,请参阅:npm - jQuery