在我的代码中读取和写入文件是非阻塞的。为什么?

Reading and writing to file is non-blocking in my code. Why?

我正在开发用于 Twitch 歌曲请求的机器人。机器人将阅读 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);
    }
}

我在阅读时遇到了问题。 运行 第一次使用 bot 时,uri.txt 文件为空。

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

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

知道为什么会这样吗?

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


编辑 2: 正如 Felix 所说,我修改了代码如下:

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;
        });
}

对吗?

正如我在评论中已经提到的,你遇到这个问题是因为你使用了承诺,即文件将在未来某个时间写入,你是尝试阅读。

正如我们所讨论的,根本不需要使用文件来“传输”该值。您可以 return 来自 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 function 使使用 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.
}