首页 > 解决方案 > 在我的代码中读取和写入文件是非阻塞的。为什么?

问题描述

我正在开发一个用于 Twitch Song Requests 的机器人。该机器人将阅读 Twitch 聊天,搜索 !sr 命令并获取歌曲名称。然后,它将在 Spotify 中搜索歌曲,获取歌曲的 URI 并将其添加到流媒体的播放列表中。

编辑:如果有任何“愚蠢”的代码问题(如回调@ippi 通知),我很抱歉,我真的是编程新手,尤其是 Node JS。

我现在有两个功能:一个是搜索歌曲并将接收到的 URI 写入文本文件,另一个是从文件中获取 URI。这是代码:

主要代码(两个函数的调用):

testSong(commandName, accessToken);

let uri = getUri();

console.log(uri);

搜索歌曲:

function testSong(song, accessToken) {
    let song1;
    let song2;

    song1 = song.replace("!sr", "");
    song2 = song1.trim();

    var uri = "";

    axios.get('https://api.spotify.com/v1/search?q=' + encodeURIComponent(song2) + '&type=track&market=CH&limit=1', {
        headers: {
            Authorization: 'Bearer ' + accessToken
        }
    })
        // handle success
        .then(function (response) {
            uri = response.data.tracks.items[0].uri;
            console.log("yeet")
            fs.writeFileSync('conf/uri.txt');
            logger.log('info', 'Successfully obtained URI for track ' + song2);
        })
        // handle error
        .catch(function (error) {
            logger.log('error', 'Error while accessing Spotify.');
            return error;
        });
}

获取 URI:

function getUri() {
    try {
        return fs.readFileSync('conf/uri.txt', 'utf-8');
    } catch (e) {
        logger.log('error', 'Error while reading the URI text file: ' + e.stack);
    }
}

我在阅读时遇到了问题。首次运行机器人时,uri.txt 文件为空。

当我在 Twitch 聊天中发送第一个 !sr 时,这首歌没有添加到 Spotify 播放列表中,因为在 getUri 函数读取文件之后,testSong 命令似乎正在写入文本文件

即使在那之后,我也必须发送一个新的 !sr 来添加第一首歌曲,所以每个请求都会被转移。

知道为什么会这样吗?

我读过异步函数,但据我了解,这不是我想要的,因为我希望在写入文本文件时阻止程序的执行,因此 getUri 函数可以读取当前请求的歌曲 URI,并且不会被移动。


编辑2:正如菲利克斯所说,我修改了代码如下:

testSong(commandName, accessToken).then(() => console.log(getUri()));
function testSong(song, accessToken) {
    let song1;
    let song2;

    song1 = song.replace("!sr", "");
    song2 = song1.trim();

    var uri = "";

    return axios.get('https://api.spotify.com/v1/search?q=' + encodeURIComponent(song2) + '&type=track&market=CH&limit=1', {
        headers: {
            Authorization: 'Bearer ' + accessToken
        }
    })
        // handle success
        .then(function (response) {
            uri = response.data.tracks.items[0].uri;
            console.log("yeet")
            fs.writeFileSync('conf/uri.txt', uri, function (err) {
                if (err) {
                    return console.log(err);
                } else {
                    response = true;
                }
            });
            logger.log('info', 'Successfully obtained URI for track ' + song2);
        })
        // handle error
        .catch(function (error) {
            logger.log('error', 'Error while accessing Spotify.');
            return error;
        });
}

那是对的吗?

标签: node.jsspotifysynchronous

解决方案


正如我在评论中已经提到的那样,您遇到此问题是因为您使用的是 Promise,即文件将在您尝试阅读之后的某个时间写入。

正如我们所讨论的,根本不需要使用文件来“传输”值。您可以从testSong(包装在承诺中)返回值:

function testSong(song, accessToken) {
    song = song.replace("!sr", "").trim();
    return axios.get('https://api.spotify.com/v1/search?q=' + encodeURIComponent(song2) + '&type=track&market=CH&limit=1', {
        headers: {
            Authorization: 'Bearer ' + accessToken
        }
    })
    // handle success
    .then(function (response) {
        return response.data.tracks.items[0].uri;
    });
    // errors should probably be handled by the caller
}

进而:

testSong(commandName, accessToken)
  .then(function(uri) {
    console.log(uri);
  })
  .catch(function(error) {
    // handle error
  });

async函数使处理 Promise 变得更容易一些。所以你也可以实现testSong

async function testSong(song, accessToken) {
    song = song.replace("!sr", "").trim();
    const response = await axios.get('https://api.spotify.com/v1/search?q=' + encodeURIComponent(song2) + '&type=track&market=CH&limit=1', {
    //               ^^^^^
        headers: {
            Authorization: 'Bearer ' + accessToken
        }
    });
    return response.data.tracks.items[0].uri.
}

推荐阅读