returning array from function in javascript

浪尽此生 提交于 2019-12-11 11:40:09

问题


so I come from a heavy python background, and I'm trying to wrap my head around javascript. Here I have a function that returns an array of track IDs for soundcloud songs by the artist 'v-2-followers'. How would I go about assigning the output of SC.get(stuff) to a variable to reuse the track list in another function. I'm sure I'm missing something fundamental. I'm less looking for an answer that explains how to do this, but more why it's done like that.

That said I would also very much appreciate the how. :)

(function() {

    SC.initialize({
        client_id:'__CLIENTID__';
    });

    // Would like to set a variable equal to the output of
    SC.get('/tracks', { q: 'v-2-followers' }, function(tracks) {
        trackIdList = [];
        tracks.forEach(function(track){
            trackIdList.push(track.id);
        });
        return trackIdList;
    });

    // And use the variable here.
    SC.stream('/tracks/'+trackIdList[Math.floor(Math.random() * myArray.length)], function(sound) {
        sound.play();
        sound.pause();
        $('#fabrizio').hover(function(e){
            sound.resume();
        }, function(e){
            sound.pause();
        });
    });
})();

I can see that I'm missing something fundamental about variable assignment and scope, or function callbacks here. I've exhausted myself skimming docs on the subject. If anyone can tell me how to do this, and more importantly, why it's done that way, for future reference.


回答1:


You have trackIdList as a global variable because it is not created using var. So as it is, you can already access it from any other function. If you wanted to limit its scope to just the outer function, add var trackIdList; as the first line of your function. You should be declaring variables with var everywhere in order to limit their scope.

(function() {
    var trackIdList;
    ...
})();

Further reading: What is the scope of variables in JavaScript?

The other concept you need to understand is regarding asynchronous execution and callbacks in JavaScript. Your code that populates trackIdList is contained within a callback function which is (most likely) called after your call to SC.stream(). If SC.stream() depends on the value of trackIdList, it should be called from the callback function.

It may help to illustrate what's going on by separating out your callback functions.

(function () {
    var trackIdList = [];

    SC.initialize({
        client_id: '__CLIENTID__'
    });

    SC.get('/tracks', { q: 'v-2-followers' }, processTracks);

    var randomIndex = Math.floor(Math.random() * myArray.length);
    SC.stream('/tracks/' + trackIdList[randomIndex], processSound);

    function processTracks(tracks) {
        tracks.forEach(function (track) {
            trackIdList.push(track.id);
        });
    }

    function processSound(sound) {
        sound.play();
        sound.pause();
        $('#fabrizio').hover(function (e) {
            sound.resume();
        }, function (e) {
            sound.pause();
        });
    }
})();

SC.get() makes an asynchronous request and returns immediately. Then SC.stream() is called without waiting for the request to return. processTracks() isn't called until the request comes back. The trouble is that SC.stream() depends on processTracks(), but is called immediately. To fix this, call SC.stream() from the callback function of SC.get():

(function () {
    SC.initialize({
        client_id: '__CLIENTID__'
    });

    SC.get('/tracks', { q: 'v-2-followers' }, processTracks);

    function processTracks(tracks) {
        var trackIdList = [];
        tracks.forEach(function (track) {
            trackIdList.push(track.id);
        });

        var randomIndex = Math.floor(Math.random() * myArray.length);
        SC.stream('/tracks/' + trackIdList[randomIndex], processSound);
    }

    function processSound(sound) {
        sound.play();
        sound.pause();
        $('#fabrizio').hover(function (e) {
            sound.resume();
        }, function (e) {
            sound.pause();
        });
    }
})();



回答2:


I'll explain one way - with callbacks. The reason people do it this way is that there are synchronous operations, and asynchronous operations. In your case, you need to perform an AJAX request - we don't know how long it will take for SC.get to finish, and we don't want the program to hang while we wait for it. So instead of waiting, we tell it "go get those tracks, and I'm passing you a function to call when you are done. In the meantime, I'm going to go on ahead with the rest of the program."

(function() {

  SC.initialize({
    client_id:'__CLIENTID__'
  });

  var getTracks = function(callback) {
    SC.get('/tracks', { q: 'v-2-followers' }, function(tracks) {
        trackIdList = [];
        tracks.forEach(function(track){
            trackIdList.push(track.id);
        });
        callback(trackIdList);
    });
  }

  // And use the variable here.
  var stream = function(trackIdList) {
    SC.stream('/tracks/'+trackIdList[Math.floor(Math.random() * myArray.length)], function(sound) {
        sound.play();
        sound.pause();
        $('#fabrizio').hover(function(e){
            sound.resume();
        }, function(e){
            sound.pause();
        });
     });
   }
   getTracks(stream);
 })();


来源:https://stackoverflow.com/questions/24644740/returning-array-from-function-in-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!