【问题标题】:.then firing before promise is resolved - $.getJSON.then 在 promise 解决之前触发 - $.getJSON
【发布时间】:2019-02-27 07:57:48
【问题描述】:

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

谢谢大家的回答!

【问题讨论】:

  • $.getJSON('/skipToNext').then(function()... 为什么不使用来自 API 的数据(函数参数为空)? changeAlbumArt 怎么知道你提取了什么?
  • 在您调用 spotify api 后,路由器会立即停止返回什么?
  • res.json(data.body) 到底是做什么的?
  • $.getJSON('/skipToNext').then(function()... 不返回数据,我已经这样做了,作为一种解决方法... changeAlbumArt 有另一个调用获取所需数据的 api。我已将该代码放在上面
  • 使用 async/await 很容易解决。

标签: javascript jquery json node.js


【解决方案1】:

$.getJSON 是一个 jQuery 方法

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

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

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

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

【讨论】:

    【解决方案2】:

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

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

    您的问题是,没有什么能阻止路由处理函数过早返回。我可能是错的,但是除了使 ajax 调用同步之外,没有像样的方法来克服这个问题,这不是一个好的做法(而且可能根本不可能使用 spotify api)。好吧,至少在 ES2017 之前不会,它引入了 async/await 构造。从节点 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 解决了,您将在从 promise 解包的 data 变量中获得返回的数据 - 如果它失败并被拒绝,将抛出异常。现在您可以输入 res 变量并让路由处理函数返回。

    【讨论】:

      猜你喜欢
      • 2020-12-27
      • 1970-01-01
      • 1970-01-01
      • 2017-09-24
      • 1970-01-01
      • 2021-09-14
      • 1970-01-01
      • 2017-10-08
      • 1970-01-01
      相关资源
      最近更新 更多