【问题标题】:Why do I seem to need both a promise and a callback to expose JSON data to a global variable?为什么我似乎需要一个 Promise 和一个回调来将 JSON 数据暴露给一个全局变量?
【发布时间】:2017-04-22 18:20:42
【问题描述】:

据我了解,将获取的 JSON 数据公开给全局变量,我需要使用 Promise 或回调函数。我的代码正在运行,但它同时使用了两者...

我正在使用 jQuery 的 .done 创建一个承诺,我想在 .done 中实例化我的 nowNext() 函数。 .done 中的代码不应该只在返回 promise(即 JSON 数据)后执行吗?

如果我此时调用nowNext() 并记录我的timeObj,它是一个空对象,但是如果我在.done 中实例化timeCall() 一个回调函数,然后实例化nowNext() 我的timeObj 得到JSON数据。

// define the timeObj globally so the returned JSON can be stored

var timeObj = {};

// function gets JSON feed, argument specifies which object within feed to target

function nowTime(i){

    $.getJSON("feed.json", function(data) {
        console.log('getting JSON...')      
    })

    // a promise only to be executed once data has been fetched
    .done(function(data) { 
        // timeData is whichever JSON object targeted in argument
        timeData = data.programme[i],

        // Start building the timeObj with this data
        timeObj = {
            title:        timeData.title,
            startTime:    timeData.start
        }

        // timeCall instantiates the nowNext function only  
        // once the timeObj has all it's key/values defined
        // directly calling nowNext at this point logs timeObj as an empty object...
        timeCall();
    })

    .fail(function() {
      console.log( "error" );
    })
};

// instantiate nowTime to fetch data of current/now programme 
$(function(){ 
    nowTime(0) 
})

// callback so that when nowNext is instantiated
// nowTime has already fetched timeObj data
function timeCall(){
    nowNext();
}

function nowNext() {
    console.log(timeObj)
}

正在获取的 JSON 数据示例:

//////// feed.json ////////

{
   "programme" : [
      {
         "title" : "Rick & Morty",
         "startTime" : "19:00",
      },
      {
         "title" : "News",
         "startTime" : "19:30",
      }
  ]
}

【问题讨论】:

  • 我不明白你在问什么。你的代码对我来说看起来不错。你传递给.done() 的函数在Promise 被解析时被调用,并且在收到getJSON() 响应时发生。在该回调中,您调用(间接)nowNext(),因此全局变量将被初始化。究竟有什么不清楚的地方?
  • 您使用多少功能取决于您。您可以将console.log(timeObj) 调用直接放在timeCall 中,甚至可以放在done 中。不会有什么不同。
  • @AlanSutherland 绝对没有理由你不能 - 请注意 console.log 有时会做一些奇怪的事情
  • 传递值是一个参数:nowNext(data.programme[i])function nowNext(data) { console.log(data) }
  • 更好的是,让.done() 执行return timeObj,然后在Promise 链中执行.then(nowNext),此时对象会自动传递

标签: javascript json ajax callback promise


【解决方案1】:

您应该避免使用全局变量。当您开始进行异步调用时,您需要确保所有以下代码都通过回调/承诺链发生,并尽可能将变量作为参数传递。

我的首选解决方案是:

function nowTime(i){   
    return $.getJSON("feed.json", function(data) {  // NB: return
        console.log('getting JSON...')      
    }).then(function(data) { 
        // timeData is whichever JSON object targeted in argument
        timeData = data.programme[i],

        // Start building a timeObj with this data
        return {
            title:        timeData.title,
            startTime:    timeData.start
        }
    });
};

function nowNext(timeObj) {
    ...
}

$(function(){ 
    nowTime(0).then(nowNext).fail(...); 
});

通过让.done 回调实际返回您需要的数据子集(尽管仍然封装在 Promise 中),然后通过 .then 调用 nowNext,您可以确保数据自动传递到 Promise 链中.

还要注意,错误处理也是通过 Promise 链完成的——如果 nowTime 函数返回一个被拒绝的 Promise(或抛出异常),则自动跳过下面的 .then 调用,代码将落入 @ 987654327@处理程序。

【讨论】:

    猜你喜欢
    • 2020-07-04
    • 2019-12-30
    • 1970-01-01
    • 2021-08-23
    • 1970-01-01
    • 2015-08-08
    • 1970-01-01
    • 2020-08-12
    • 2013-05-11
    相关资源
    最近更新 更多