异步 axios 不使用 NODEJS 运行承诺

Posted

技术标签:

【中文标题】异步 axios 不使用 NODEJS 运行承诺【英文标题】:Async axios dont run promise using NODEJS 【发布时间】:2018-06-09 23:46:31 【问题描述】:

我正在开发一个多人游戏,在客户端使用 vue 并使用 nojejs 作为游戏服务器(我使用vue-sockets.io 与客户端和服务器通信)。 当我在节点端创建游戏实例时,它将具有图块并隐藏(两个图像数组都来自 api)。对于这个使用axios,问题是创建的游戏在运行axios之前返回给客户端。所以客户端会得到没有图像的游戏。

createGame(playerName, socketID, boardSize) 
    this.contadorID = this.contadorID+1;

        var game = new MemoryGame(this.contadorID, playerName, boardSize);

        new Promise(function(resolve, reject) 
            console.log("a");
            game.getTiles().then(response=>
                console.log("getTiles");
        game.tiles = game.getRandomNPieces(response.data.data, game.board.length/2);
                console.log(game.tiles);
      ).catch(function (error) 
        console.log(error);
      );
            console.log('=>' + game.tiles);
        ).then(function(result)  // (***)
            console.log("b");
          game.getHidden().then(response=>
        game.hidden = game.getRandomHidden(response.data.data);
      ).catch(function (error) 
        console.log(error);
      );
        ).catch(function (error) 
            console.log(error);
        );
    game.player1SocketID = socketID;
    this.games.set(game.gameID, game);
    return game;

程序永远不会到达第二个 axios 调用。 gameList 日志来自返回给用户的游戏。

客户端 1 中的游戏实例(创建游戏的人):

客户端 2 中的游戏实例(游戏在大厅并且已经有图块):

【问题讨论】:

为了有效地帮助您,您需要将代码的相关部分作为文本粘贴到问题中,并将它们格式化为代码。然后,我们可以复制/粘贴其中的一部分并进行更正。代码不应仅作为图像的外部链接提供。它应该作为文本粘贴到您的问题中。这些是堆栈溢出的规则/指南。您的代码有很多问题,但我不会手动从图像中重新键入您的所有代码,以便向您展示如何修复它。 @jfriend00 感谢您的建议!我将在这里传递我的代码! 我不确定这段代码应该做什么,因为您有异步操作,但正在尝试同步返回尚未操作的game 对象,但第一个核心问题就是你创建了new Promise(),但你从不调用resolve()reject() 来解决或拒绝该承诺。你展示的是一个承诺反模式。无需将来自getTiles() 的现有承诺包装在另一个承诺中。您可以只使用它返回的承诺。这段代码有很多问题。不知道它的目标是什么。 @jfriend00 在此之前我只使用 axios,但这里的问题是:该方法将游戏实例返回给客户端,然后他运行 axios 代码。因此,客户端将获得没有图像的游戏。现在我尝试使用 resolve() 并且我的代码现在到达了两个 axios 调用,但只有在返回对象之后 【参考方案1】:

由于createGame() 似乎依赖一些异步操作来正确初始化游戏,因此您不能只从createGame() 同步返回已完成的游戏对象。正如您已经观察到的,createGame() 将在任何异步操作完成之前返回游戏对象。因此,相反,您需要返回一个 promise,其解析值为游戏对象,然后您需要将所有异步操作正确链接在一起,以便在游戏对象全部完成后解析您的主要 promise。这是一种结构方式:

createGame(playerName, socketID, boardSize) 
    this.contadorID = this.contadorID+1;

    var game = new MemoryGame(this.contadorID, playerName, boardSize);

    console.log("a");
    return game.getTiles().then(response=> 
        console.log("getTiles");
        game.tiles = game.getRandomNPieces(response.data.data, game.board.length/2);
        console.log(game.tiles);
        console.log('=>' + game.tiles);
        console.log("b");
        // return nested promise so it chains into main promise chain
        return game.getHidden().then(response=>
            game.hidden = game.getRandomHidden(response.data.data);
        );
    ).then(() => 
        // finish initializing game object and 
        // make it be the resolved value of the returned promise
        game.player1SocketID = socketID;
        this.games.set(game.gameID, game);
        return game;
    ).catch(function (error) 
        // log error and rethrow so promise stays rejected
        // this will log for any of our rejected promises since they are chained
        console.log(error);
        throw error;
    );

而且,这会更改 createGame() 以返回一个承诺,因此您必须像这样更改使用它的方式:

someObj.createGame(...).then(game => 
    // game object is ready to use here
).catch(err => 
    // error creating game object
);

【讨论】:

以上是关于异步 axios 不使用 NODEJS 运行承诺的主要内容,如果未能解决你的问题,请参考以下文章

nodejs 中的异步和 Q 承诺

刷新承诺队列?

Nodejs 异步承诺队列

JavaScript NodeJS 如何将流/承诺与异步函数一起使用?

我可以在nodejs(ES7)中解雇并忘记一个承诺吗?

NodeJs分页,递归承诺问题