.then在承诺解决之前触发-$ .getJSON

时间:2018-09-23 17:30:54

标签: javascript jquery json node.js

我目前正在使用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 + ")");
  });
};

感谢所有回答!

2 个答案:

答案 0 :(得分:0)

$。getJSON是jQuery方法

jQuery不使用原生Promise(带有then / catch构造函数)

jQuery重新实现了称为Deferred的概念。

要正确等待getJSON complete事件,您必须像这样编写代码

$.getJSON('/currentPlayback')
.done( function(data) {
   // Data arrived
}).fail(function(e,xhr){
   // Error occurred
}).always(function(){
   //always callback
})

答案 1 :(得分:0)

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

  1. 进入路由处理程序功能,启动Spotify api调用。
  2. 这将返回一个诺言(我假设),在其中附加一个延续函数,并且res被捕获在闭包中。
  3. 这时,路由处理程序函数和平返回,因为该函数已完成对请求的处理。
  4. 有时,api调用返回(假设成功)并且诺言得以解决。
  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调用返回。然后恢复功能。如果承诺被解决,您将在data变量中获得返回的数据,并从承诺中解包出来-如果失败并被拒绝,将抛出异常。现在,您可以输入res变量,并让路由处理函数返回。