首页 > 解决方案 > .then 在 promise 解决之前触发 - $.getJSON

问题描述

我目前正在使用 Spotify API 和 nodejs 包装器构建一个 Web 应用程序......但是,当我使用 $.getJSON() 时,.then 在承诺解决之前触发。例如,在我跳到下一首歌曲后,我试图更改网页上显示的专辑插图。但是,艺术品首先在歌曲之前发生变化,因此艺术品始终是上一首歌的……我的代码在下面。

index.js 中的路由:

router.get('/skipToNext', function skipToNext(req, res, next) {
  spotifyApi.skipToNext()
  .then(function(data) {
    res.json(data.body);
  }, function(err) {
    console.log("Something went wrong! ", err);
  });
});

我跳过歌曲的功能:

function skipToNext() {
  $.getJSON('/skipToNext')
  .then(function() {
    changeAlbumArt();
  }, function(err) {
    console.log("error! ", err);
  });
};

changAlbumArt:

function changeAlbumArt() {
  $.getJSON('/currentPlayback')
    .then( function(data) {
      console.log("Change album art: " + data);
      var albumCover = data.item.album.images[0];
      var albumName = data.item.album.name;
      var albumCoverUrl = albumCover["url"];
      console.log("url: " + albumCoverUrl);
      console.log("album name: " + albumName);
      console.log("now playing: " + data);
      $(".container-album-cover").css("background", "url(" + albumCoverUrl + ")");
  });
};

谢谢大家的回答!

标签: javascriptjqueryjsonnode.js

解决方案


查看路由代码,注意执行顺序:

  1. Route handler 函数进入,spotify api 调用开始。
  2. 这将返回一个承诺(我假设),在其中附加一个延续函数,并res在闭包中捕获。
  3. 此时,路由处理函数和平返回,因为该函数已完成对请求的处理。
  4. 一段时间后,api 调用返回(假设成功)并且 promise 解决了。
  5. res.json(data.body)被调用,但周围没有更多的上下文,因此这永远不会到达客户端。

您的问题是,没有什么能阻止路由处理程序函数过早返回。我可能是错的,但是除了使 ajax 调用同步之外,没有像样的方法来克服这个问题,这不是一个好的做法(而且可能根本不可能使用 spotify api)。好吧,至少在引入async/await构造的 ES2017 之前不会。从节点 7.6 开始,您可以通过以下方式重写您的服务器代码:

router.get('/skipToNext', async (req, res, next) => {
    try {
        let data = await spotifyApi.skipToNext();
        res.json(data.body);
    } catch (err) {
        console.log("Something went wrong! ", err);
    };
});

这样,您的路由处理程序函数将暂停,直到 api 调用返回。然后恢复该功能。如果 Promise 解决了,您将在data从 Promise 中解包的变量中获取返回的数据 - 如果它失败并被拒绝,将抛出异常。现在您可以输入res变量并让路由处理函数返回。


推荐阅读