如何将异步信息添加到全局数组? [英] How to go about adding asynchronous information to a global array?

查看:57
本文介绍了如何将异步信息添加到全局数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习 Node JS 以及如何访问 API 的信息,但我遇到了一个问题,即当我将值推送到数组时,信息永远不会被全局添加.

I'm learning Node JS as well as how to access an API's information, and I've come across a problem where when I push values to an array, the info never gets added globally.

所以假设我有 var albIds= new Array(5),这些值永远不会被添加.通过查看 thisthis 我现在知道问题是信息在我调用它时永远不会进入数组,因为同步代码首先完成,但是,我对如何使同步等待异步完成感到困惑.

So let's say I have var albIds= new Array(5), the values never get added. Through looking at this and this I now know that the issue is that the information never gets into the array by the time I call it, due to the synchronous code being done first, however, I am confused at how to make the synchronous wait for the asynchronous to complete.

到目前为止我的代码.

//prints out albums 1-5 id's
var id = '3TVXtAsR1Inumwj472S9r4';
var albIds= new Array(5);
async function getAlbums(i) {

var authOptions = {
  url: 'https://accounts.spotify.com/api/token',
  headers: {
    'Authorization': 'Basic ' + (new Buffer.from(client_id + ':' + client_secret).toString('base64'))
  },
  form: {
    grant_type: 'client_credentials'
  },
  json: true
};

request.post(authOptions, function(error, response, body) {
  if (!error && response.statusCode === 200) {

    // use the access token to access the Spotify Web API
    // const querystring = require('querystring');

const data = {
  market: "US",
  limit: "5"
};
const  q = querystring.stringify(data);
    var token = body.access_token;
    var options = {
      url: 'https://api.spotify.com/v1/artists/'+id+'/albums?'+q,
      headers: {
        'Authorization': 'Bearer ' + token
      },
      json: true
    };
  request.get(options, function(error, response, body)
     {
  for(var i = 0; i<5;i++)
      {
       albIds.push(body.items[i].id);
      }
});
}

})
};

async function fetchUsers()
{
  for(var i = 0;i<5;i++)
  {
    await getAlbums(i);
    console.log(albIds[i]);
  }
}
fetchUsers();

任何帮助表示赞赏.作为参考,我正在使用 Spotify 的 API

Any help appreciated. For reference, I'm using Spotify's API

推荐答案

仅供参考,albIds 不是全局的.这是一个模块范围的变量.

FYI, albIds is NOT a global. It's a module scoped variable.

然后,您需要了解 await 只有在您等待与异步操作完成相关的承诺时才会做一些有用的事情.您的 getAlbums() 函数并非如此.虽然它被声明为 async 所以它确实返回了一个承诺,但该承诺与异步操作的完成完全无关.

Then, you need to understand that await ONLY does something useful if you are awaiting a promise that is connected to the completion of your asynchronous operation. That is NOT the case for your getAlbums() function. While it's declared async so it does return a promise, that promise is not connected at all to the completion of your asynchronous operations.

相反,在您将任何数据放入 albIds 数组之前很久,promise 就完成了.因此,您认为该数组是空的(因为在您尝试使用它时尚未将任何内容放入其中).

Instead, the promise completes, long before you've put any data into the albIds array. Thus, you think the array is empty (because nothing has yet been put into it when you're trying to use it).

这是我的建议:

const rp = require('request-promise');

//prints out albums 1-5 id's
const id = '3TVXtAsR1Inumwj472S9r4';

async function getAlbums(i) {
    const albIds = new Array(5);

    const authOptions = {
        url: 'https://accounts.spotify.com/api/token',
        headers: {'Authorization': 'Basic ' + (new Buffer.from(client_id + ':' + client_secret).toString('base64'))},
        form: {grant_type: 'client_credentials'},
        json: true
    };

    const body = await rp.post(authOptions, function(error, response, body) {

    const data = {
        market: "US",
        limit: "5"
    };
    const q = querystring.stringify(data);
    const token = body.access_token;
    const options = {
        url: 'https://api.spotify.com/v1/artists/' + id + '/albums?' + q,
        headers: { 'Authorization': 'Bearer ' + token },
        json: true
    };
    let result = await rp.get(options);

    for (let j = 0; j < 5; j++) {
        albIds.push(result.items[j].id);
    }
    // let resolved value be the array
    return albIds;
};

async function fetchUsers() {
    for (let i = 0; i < 5; i++) {
        const albiIds = await getAlbums(i);
        console.log(albIds[i]);
    }
}
fetchUsers();

变更摘要:

  1. 切换到 request-promise 库,该库使用 Promise 来传达结果并自动检查 2xx 状态.这与 async 函数更加兼容,我们可以将 await 与它一起使用.
  2. 使 albIds 成为 getAlbums() 的已解析值,而不是更高范围的共享变量(对并发问题更免疫,它确保您不能在它准备好之前尝试使用它).
  3. fetchUsers()中,使用来自getAlbums()返回的promise的albIds.
  4. 根据需要将所有变量更改为 letconst(此处根本不需要使用 var).
  5. 在请求-承诺调用上使用 await 以简化代码流并与 getAlbums() 返回的承诺兼容.
  1. Switch to the request-promise library that uses promises to communicate results and checks for a 2xx status automatically. This is much more compatible with an async function and we can use await with it.
  2. Make the albIds be the resolved value of getAlbums() rather than a higher scoped, shared variable (much more immune to concurrency issues and it ensures you can't attempt to use it before it's ready).
  3. In fetchUsers(), use the albIds that comes from the promise returned by getAlbums().
  4. Change all variables to let or const as appropriate (no need to use var here at all).
  5. Use await on the request-promise calls to simplify the code flow and to be compatible with the promise that getAlbums() is returning.

<小时>

仅供参考,如果这是相当新的代码,我将停止使用 requestrequest-promise 库,因为它们已被正式弃用以用于新的开发.虽然它们会得到维护,但随着时间的推移,它们不会添加新功能.你可以读到为什么会发生这种情况,但基本上它们已经存在了很长时间,而且 node.js 在那段时间里发生了很大的变化,以至于它们变得有点混乱,难以维护和前进.但是,有如此多的用户,他们无法真正对 API 进行重大更改,以便真正继续向前推进(例如使其完全由承诺驱动).而且,由于有许多具有更现代设计的优秀替代品,因此他们决定将未来转向其他替代品.我个人在大多数情况下都使用 got(),但还有许多其他替代方案可供选择.


FYI, if this is fairly new code, I would stop using the request or request-promise libraries as they are officially deprecated for new development. While they will be maintained, they will not be getting new features added to them over time. You can read why this is happening, but basically they've been around so long and node.js has changed so much during that time that they've become a bit of a mess to maintain and move forward. But, there are so many users that they can't really make the breaking changes to the API that they would have to in order to really continue to move it forward (like make it entirely promise-driven). And, since there are a number of good alternatives that have a more modern design, they've decided to turn the future over to the other alternatives. I'm personally using got() for most of my uses, but there are numerous other alternatives to choose from.

请参阅我应该使用新项目的请求"模块?了解更多信息.

这篇关于如何将异步信息添加到全局数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆