【问题标题】:How to solve the pyramid of doom with async/await?如何用 async/await 解决厄运金字塔?
【发布时间】:2019-02-19 06:48:33
【问题描述】:

我想知道如何避免这段代码的末日金字塔:

原始代码

var PlayerService = {
    getPlayerTeamId: function(playerId, callback) {
        $.ajax({
            url: "/player/" + playerId + "/team",
            success: function(team) {
                callback(team.id)
            }
        });
    },
    getPlayers: function(teamId, callback) {
        $.ajax({
            url: "/team/" + teamId + "/player",
            success: callback
        });
    }
};

var PlayerDetailsController = {
    playerId: 8,
    showTeammatesClick: function() {
        PlayerService.getPlayerTeamId(this.playerId, function(teamId) {
            PlayerService.getPlayers(teamId, function(playerList) {
                // Render playerList
            });
        });
    }
};

这是我的 async/await 版本,以避免 sol 金字塔: 我的版本

var PlayerService = {
    getPlayerTeamId: async function(playerId, callback) {
        return await $.ajax({
                   url: "/player/" + playerId + "/team",
                   success: function(team) {
                       callback(team.id)
                   }
               });
    },
    getPlayers: async function(teamId, callback) {
        return await $.ajax({
                   url: "/team/" + teamId + "/player",
                   success: callback
               });
    }
};

var PlayerDetailsController = {
    playerId: 8,
    showTeammatesClick: function() {
        PlayerService.getPlayerTeamId(this.playerId, function(teamId) {
            PlayerService.getPlayers(teamId, function(playerList) {
                // Render playerList
            });
        });
    }
};

可以吗?或者我怎样才能正确使用这个异步/等待?我正在尝试“getPlayerTeamId”和“getPlayers”不应该期望回调参数,并以任何方式避免回调。

有什么建议吗?谢谢,祝你有美好的一天:D

【问题讨论】:

标签: javascript ecmascript-6 es6-promise


【解决方案1】:

厄运金字塔不是通过将async/await 放置在某个地方来解决的,而是通过返回和链接承诺而不是接受回调。请注意,您的服务方法甚至不需要是async,因为它们可以返回一个承诺 - 在任何情况下都是don't use return await:

const PlayerService = {
    getPlayerTeamId(playerId ) {
//                          ^ no callback
        return $.ajax({
//      ^^^^^^ the promise
            url: "/player/" + playerId + "/team"
        }).then(team => team.id);
    },
    // same here
    getPlayers(teamId) {
        return $.ajax({
            url: "/team/" + teamId + "/player"
        });
    }
};

现在promisification 已经完成,我们可以开始使用promise .then() 或await 语法,而不是在调用这些方法时嵌套回调:

const PlayerDetailsController = {
    playerId: 8,
    async showTeammatesClick() {
        const teamId = await PlayerService.getPlayerTeamId(this.playerId);
        const playerList = await PlayerService.getPlayers(teamId);
        … // Render playerList
    }
};

【讨论】:

    【解决方案2】:

    我假设如果您使用的是 async/await,那么您的代码库在 ES6 中。

    所以你实际上可以只使用Fetch API 来替换$.ajax({...}) 语法:

    var PlayerService = {
        getPlayerTeamId: function(playerId) {
            return fetch(`/player/${playerId}/team`);
        },
        getPlayers: function(teamId) {
            return fetch(`/team/${teamId}/player`);
        }
    };
    
    var PlayerDetailsController = {
        playerId: 8,
        showTeammatesClick: async function() {
            const teamId = await PlayerService.getPlayerTeamId(this.playerId);
            const playerList = await PlayerService.getPlayers(teamId);
    
            /* Render playerList here */
        }
    };
    

    使用 async/await 或 Promises 的目的是避免回调,从而解决了“厄运金字塔”。

    因此,在构建 PlayerService 函数时,您可以完全跳过 callback 参数。

    或者,您也可以只使用普通的Promise syntax:

    var PlayerService = {
        getPlayerTeamId: function(playerId) {
            return fetch(`/player/${playerId}/team`);
        },
        getPlayers: function(teamId) {
            return fetch(`/team/${teamId}/player`);
        }
    };
    
    var PlayerDetailsController = {
        playerId: 8,
        showTeammatesClick: function() {
            PlayerService.getPlayerTeamId(this.playerId)
              .then(PlayerService.getPlayers)
              .then(playerList => {
                  /* Render playerList here */
              });
        }
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-04
      • 2018-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-04
      相关资源
      最近更新 更多