React应用中Spotify-web-api-js多实例创建异常求助
问题:spotify-web-api-js 多实例共享 Access Token 导致覆盖问题
我用spotify-web-api-js开发React应用,这个库的常规用法是这样的:
let SpotifyWebApi = require('spotify-web-api-js'); let spotifyApi = new SpotifyWebApi(); spotifyApi.setAccessToken("AccessToken") spotifyApi.getPlaylist("playlistLink")
因为需要给不同用户用独立的access token,我创建了两个实例,结果发现它们根本不是独立的——后设置的token会覆盖所有实例的token:
let SpotifyWebApi = require('spotify-web-api-js'); let spotifyApi1 = new SpotifyWebApi(); let spotifyApi2 = new SpotifyWebApi(); console.log(spotifyApi1.getAccessToken()); console.log(spotifyApi2.getAccessToken()); spotifyApi1.setAccessToken("Hello"); spotifyApi2.setAccessToken("Bye"); console.log(spotifyApi1.getAccessToken()); console.log(spotifyApi2.getAccessToken());
实际输出:
null null Bye Bye
预期输出应该是:
null null Hello Bye
哪怕重复require包再创建实例,问题还是一样。
原因分析
这个库的设计存在缺陷——它的内部状态(包括access token)是全局共享的,并非每个实例独立维护。所有通过new SpotifyWebApi()创建的实例,读写的都是同一个全局变量,自然会出现互相覆盖的情况。
解决方案
方案1:手动封装独立实例
重写实例的token相关方法,让每个实例维护自己的专属token:
let SpotifyWebApi = require('spotify-web-api-js'); function createIndependentSpotifyInstance() { const instance = new SpotifyWebApi(); // 给实例添加专属的token存储 instance._privateToken = null; // 重写设置token的方法 instance.setAccessToken = function(token) { this._privateToken = token; }; // 重写获取token的方法 instance.getAccessToken = function() { return this._privateToken; }; // 重写底层请求方法,让它用实例自己的token const originalRequest = instance._request; instance._request = function(options) { options.headers = options.headers || {}; options.headers['Authorization'] = `Bearer ${this._privateToken}`; return originalRequest.call(this, options); }; return instance; } // 使用示例 const api1 = createIndependentSpotifyInstance(); const api2 = createIndependentSpotifyInstance(); api1.setAccessToken("Hello"); api2.setAccessToken("Bye"); console.log(api1.getAccessToken()); // Hello console.log(api2.getAccessToken()); // Bye
方案2:换用官方推荐的SDK
放弃这个问题库,改用Spotify官方的@spotify/web-api-ts-sdk,它原生支持多实例独立状态:
import { SpotifyApi } from '@spotify/web-api-ts-sdk'; // 创建实例1 const api1 = SpotifyApi.withAccessToken('https://api.spotify.com/v1', 'Hello'); // 创建实例2 const api2 = SpotifyApi.withAccessToken('https://api.spotify.com/v1', 'Bye'); // 各自独立使用 api1.playlists.getPlaylist('xxx'); api2.playlists.getPlaylist('yyy');
方案3:直接调用原生API
如果不想依赖第三方库,直接用fetch或axios封装请求,每次请求携带对应用户的token:
async function getPlaylist(playlistId, accessToken) { const response = await fetch(`https://api.spotify.com/v1/playlists/${playlistId}`, { headers: { 'Authorization': `Bearer ${accessToken}` } }); return response.json(); } // 使用时传入对应token getPlaylist('xxx', 'Hello'); getPlaylist('yyy', 'Bye');
内容的提问来源于stack exchange,提问作者Parsa
相关产品推荐
相关产品推荐

