【问题标题】:return Json.Stringfy result返回 Json.Stringify 结果
【发布时间】:2016-09-02 07:50:10
【问题描述】:

我有这段代码:

$.getJSON('http://myjsonurl', function(json){console.log(JSON.stringify(json.columns)); });

这会在控制台中返回我从 json 响应中需要的所有内容。我的目标是将这个值放入一个函数中,以便我可以在另一个地方调用它。 (例如:

"columns" : getColumns();

所以我正在制作这样的功能:

function getColumns() {
    $.getJSON('http://myjsonurl', function(json){return JSON.stringify(json.columns); });
    }

console.log(getColumns()); // and then call the function in the console log expecting to see the same result as before.

但我得到的只是未定义的。 为什么?

更新:

这就是我实现我想要的方式的方式。以下代码将根据带有数据和列的 json 响应重新启动数据表(数据表本身不支持的内容)。该代码将使用新的查询参数重新加载表格并包含按钮插件:

var theurl;
theurl = "http://myjson.json";


function updateQueryStringParameternondt(key, value) {
    var table = $('#datatable-buttons').DataTable();
    var ajaxurl = theurl;   
  var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
  var separator = ajaxurl.indexOf('?') !== -1 ? "&" : "?";
  if (ajaxurl.match(re)) {
    console.log( ajaxurl.replace(re, '$1' + key + "=" + value + '$2'));
    theurl = ajaxurl.replace(re, '$1' + key + "=" + value + '$2');
    table.destroy();
    TableManageButtons.init();

  }
  else {
       console.log( ajaxurl + separator + key + "=" + value);
    theurl =  ajaxurl + separator + key + "=" + value ;
    table.destroy();
    TableManageButtons.init();
  }
}

TableManageButtons.init();

var handleDataTableButtons = function() {


        0 !== $("#datatable-buttons").length && 

    $.ajax( {
  url:theurl,
  dataType: 'json',
  success: function ( json ) {

      $("#datatable-buttons").DataTable({
        "data" : json.data,
        "columns": json.columns,    
            dom: "Bfrtip",
            buttons: [{
                extend: "copy",
                className: "btn-sm"
            }, {
                extend: "csv",
                className: "btn-sm"
            }, {
                extend: "excel",
                className: "btn-sm"
            }, {
                extend: "pdf",
                className: "btn-sm"
            }, {
                extend: "print",
                className: "btn-sm"
            }],
            responsive: !0
        });
         }
} );
    },
    TableManageButtons = function() {
        "use strict";
        return {
            init: function() {
                handleDataTableButtons();
            }
        };
    }();

【问题讨论】:

  • function getColumns() { return $.getJSON('myjsonurl', function(json){return JSON.stringify(json.columns); }); }
  • @Ioannis Kokkinis 您应该从 $.getJSON 方法返回处理程序的响应以及 Promise 并处理它。我会提供一个简单的解释来解释自己。
  • getColumns("$('#datatable-buttons').DataTable().ajax.url").always(function (response) { thecolumns = response;}); 行将异步运行,因此不会设置thecolumns 变量的值。异步的意思是JavaScript会运行所有代码直到结束,然后会运行异步“标记”的代码,大致解释一下。所以试着把你所有的数据表实例化逻辑放在回调中。

标签: javascript jquery json datatables stringify


【解决方案1】:

@guest271314 答案是正确的,应该可以指导您解决有关从getColumns 方法返回未定义的问题。

我只想在这里指出一些关键的事情。

首先调查我刚才创建的plunk。如您所见,这里的所有作用都是操纵 Deferred 对象(有关更多信息,请参阅here)。粗略地解释一下,Deferred 对象可以注册回调,如果您喜欢多个回调,请将它们链接起来,通过调用它们可以广播它们的状态以及它们的响应。它基于 Promise 设计,因此此类方法返回一个 Promise,可以同步或异步解析(大多数时候 Promise 在异步操作中很有用)。

jQuery 的异步方法,例如 $.ajax 返回一个承诺。 $.getJSON 没有什么不同,因为它最后调用 $.ajax,如前所述,它返回一个 jQuery Deferred Promise。

对于 jQuery 的 animation 方法,请参阅下面的 @guest271314 评论。

更多关于承诺here

来自文档

返回一个 Promise 对象以观察绑定到集合的特定类型的所有操作(无论是否排队)都已完成。

promise,在处理时会解决拒绝resolve 代表成功响应,reject 代表失败。 从文档中我们可以看到Deferred 对象的方法可以处理成功、失败或两者兼而有之。

deferred.done() 添加延迟对象时要调用的处理程序 解决了。​​

deferred.fail() 添加要在 Deferred 对象被拒绝时调用的处理程序。

deferred.always() 添加要在 Deferred 对象被解析或拒绝时调用的处理程序。

那么,让我们回到 OP 的问题。正如您现在从代码中看到的那样:

function getColumns() {
    $.getJSON('http://myjsonurl', function(json){return JSON.stringify(json.columns); });
}

您无法知道getColumns 状态,因为您不返回promise。当使用 $.getJSON 处理程序时,您实际上是在处理响应而不发出承诺对象。 getColumns 函数当然会返回 undefined,因为没有 return 的符号,默认情况下你会得到它。

关于deferred.then() 方法,您也可以使用它处理promise,处理它的状态和进度。在上面发布的 Plunker 示例代码中,我不关心进度,只关心状态,所以在第一个示例中,promise 使用 .then() 方法处理,第一个函数是成功处理程序,而第二个函数是失败处理程序。从他们那里返回响应本质上意味着承诺得到解决。我也返回了承诺本身。

在注释掉的部分中,您可以看到如果您愿意,您可以只返回承诺并解决 always 方法中的响应

【讨论】:

  • 当我在数据表初始化时:"columns": getColumns("myjson.json").always(function (response) { return response; }),我仍然没有得到响应.这可能是因为数据表在返回值之前尝试初始化?
  • 请更新您的问题,同时添加 jQuery 数据表初始化代码。
  • 我想我需要在数据表的初始化之前添加承诺结果?
  • @gdyrrahitis .animate() 返回 jQuery() 对象;返回 jQuery 承诺可以将 .promise() 链接到元素或集合,或者在调用 .animate() 的函数之外的动画选择器或对象上调用 .promise()
【解决方案2】:

正如@MiguelBolan 所指出的,getColmuns() 没有返回任何值。 return$.getJSON()来自getColumns();使用.then() 访问从异步函数返回的值

function getColumns() {
  return $.getJSON("http://myjsonurl");
}

getColumns().then(function(json) {
  console.log(JSON.stringify(json.columns))
}
// handle errors
, function err(jqxhr, textStatus, errorThrown) { 
    console.log(textStatus, errorThrown)
}; 

【讨论】:

  • @IoannisKokkinis 注意,console.log(getColumns()); 可以在 $.getJSON() 完成 js 之前调用。此外,getColumns() 的返回值将是一个 jQuery 承诺对象,而不是 json.columns 作为JSON 字符串。 jQuery 承诺值可以通过$.getJSON() 完成回调或在帖子中使用的.then() 访问;或者您可以使用.always() 访问来自$.getJSON()successerror 结果
【解决方案3】:

您的getColumns() 函数需要返回变量,目前它只是返回给函数而不是输出。尝试这个: {

function getColumns() {
    var ret;
    $.getJSON('http://myjsonurl', function(json){
          ret = JSON.stringify(json.columns); 
          });
    return ret;
    }

【讨论】:

  • 当我执行 console.log(getColumns()); 时仍然不确定对 json 的调用是否可能需要时间才能赶上?
  • 您可以使用$.ajaxSetup({ async: false }); 同步运行它(在执行$.getJSON 之前添加该行),尽管在分配ret 的值之后将打印语句移动到function(json){...} 会更容易。
  • 基于此:stackoverflow.com/questions/2465446/… 似乎异步可能是要走的路,运气好吗?
  • $.getJSON 是异步的,返回一个 Promise,意思是在 JavaScript 中这段代码是排队的,会继续执行,直到没有剩下一行。然后 JavaScript 会在队列中请求这个并处理它。所以,这种方法是错误的。应该并且必须使用 Promise API 方法处理承诺。 Promises 文档:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
猜你喜欢
  • 2011-11-07
  • 1970-01-01
  • 1970-01-01
  • 2015-01-24
  • 1970-01-01
  • 2017-12-30
  • 1970-01-01
  • 2020-11-12
  • 2015-11-11
相关资源
最近更新 更多