我正在编写一个基于浏览器并在后端使用 Nodejs 的 Cmus Remote。该应用程序的一部分涉及获取当前播放的歌曲并将其显示给用户。
目前,它成功运行命令,将输出正确存储到变量中,但客户端请求在服务器端函数回调之前运行,因此它会重新运行歌曲的空字符串。
下面的代码可以更好地说明我的意思:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Cmus Remote</title>
<script src="client.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body id="body">
</body>
</html>
client.js
"use strict";
window.onload = function () {
$.get("/songInfo", function(string){
alert(string);
});
};
server.js
var express = require('express');
var app = express();
var path = require('path');
var exec = require('child_process').exec;
var fs = require('fs');
var child;
var getSongCommand = "cmus-remote -Q | sed -n -e 's/^.*tag title //p'";
var getAlbumCommand = "cmus-remote -Q | sed -n -e 's/^.*tag album //p'";
var getArtistCommand = "cmus-remote -Q | sed -n -e 's/^.*tag artist //p'";
var song ="";
var album= "";
var artist = "";
app.use(express.static(__dirname + '/public'));
app.get('/', function (req, res){
res.sendFile(path.join(__dirname + '/index.html'));
});
app.get('/songInfo', function(req, res){
updateSongInfo(getSongCommand);
updateSongInfo(getAlbumCommand);
updateSongInfo(getArtistCommand);
var strings = [song, artist, album];
res.send(strings);
});
var server = app.listen(8080, function () {
console.log("Server online");
});
function updateSongInfo(command){
var exec = require('child_process').exec;
exec(command, function(error, stdout, stderr){
callback(command, stdout);
});
}
function callback(commandRan, output){
console.log("Commandran = " + commandRan);
console.log("Command output = " + output);
if(commandRan.includes("title")){
console.log("Updating song to " + output);
song = output;
}
if(commandRan.includes("album")){
album = output;
}
if(commandRan.includes("artist")){
artist = output;
}
// console.log("In callback");
// console.log(output);
return output;
}
总而言之,ajax 响应工作正常,命令运行正常,并且值被保存到我拥有的 3 个全局变量中,但我不确定如何设置变量完成后 ajax 请求返回的时间值。
最佳答案
问题是因为 exec 是异步的,所以 exec 将被调用,程序将继续并将仍然为空的数据返回给调用者,然后它将以现在收到的执行数据完成。
要解决此问题,您可以使用 Promise 和 async/await。
app.get('/songInfo', async function(req, res){
await updateSongInfo(getSongCommand);
await updateSongInfo(getAlbumCommand);
await updateSongInfo(getArtistCommand);
var strings = [song, artist, album];
res.send(strings);
});
...
function updateSongInfo(command){
return new Promise((resolve, reject) => {
var exec = require('child_process').exec;
exec(command, function(error, stdout, stderr){
callback(command, stdout);
return resolve();
});
});
}
在Promise中调用resolve()将完成它,而调用reject()将抛出错误。您也可以为这些函数提供参数。
关于javascript - Nodejs通过回调方法发送ajax给客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46356429/