Javascript 如何将从API获取的数据添加到HTML数据表?

Javascript 如何将从API获取的数据添加到HTML数据表?,javascript,datatable,Javascript,Datatable,我试图用从API收集的信息来完成一个数据表 我在这里做了一个“提琴”,以便于帮助和理解我的意思: 我从一个只包含ID的HTML表开始。然后,我在rowCallback中使用该ID调用API,并使用jQuery$('td:eq(1)”,nRow.html(json.Title)将获取的值写入表中 但是,这里的问题是无法在第二列上排序。即使你能很好地看到数据。我打赌DataTable并不真正知道有新数据,结果是对空值进行排序,而不是对添加的值进行排序 这个问题的第二个影响(在我的小提琴中没有显示)

我试图用从API收集的信息来完成一个数据表

我在这里做了一个“提琴”,以便于帮助和理解我的意思:

我从一个只包含ID的HTML表开始。然后,我在rowCallback中使用该ID调用API,并使用jQuery
$('td:eq(1)”,nRow.html(json.Title)将获取的值写入表中

但是,这里的问题是无法在第二列上排序。即使你能很好地看到数据。我打赌DataTable并不真正知道有新数据,结果是对空值进行排序,而不是对添加的值进行排序

这个问题的第二个影响(在我的小提琴中没有显示)是折叠的行(宽度不够时行应该折叠)在行展开时也显示为空。
第三个影响是搜索对获取的数据不起作用

是否有办法将提取的数据添加到数据表中?不是在化妆上


(注意:我能找到的所有响应都是关于用AJAX请求填充完整的DataTable。我只是向已填充的DataTable添加数据)

你说得对,DataTable不知道要排序的表中有什么。 我想说的是,一旦表格完成,就运行这个函数

$('#example').find('tbody tr').each(customFnRowCallback);

function customFnRowCallback()
{
  var $this = $(this);
  var imdbID = $this.find('td:eq(0)').text();

  fetch("http://www.omdbapi.com/?i="+imdbID+"&plot=short&r=json&tomatoes=true")
  .then(function(response) {
    return response.json();
  })
  .then(function(json) {
    $this.find('td:eq(1)').text( json.Title );
  })
  .then(function() {
    $('#example').DataTable();
  })
  .catch(function(error) {
    console.log('There has been a problem with your fetch operation: ' + error.message);
  });
}

我采取了不同的方法。我将datatableajax与when/done一起使用,因此在处理所有get之前,它不会刷新表

我设置了排序,所以列表将按字母顺序显示,即使那些不是列表的顺序。 我还从imdb获得了一组唯一的值


//来自的样本返回集
var sampleReturn={“标题”:“七武士”,“年份”:“1954年”,“评级”:“未评级”,“发布”:“1956年11月19日”,“运行时”:“207分钟”,“流派”:“冒险,戏剧”,“导演”:“黑泽明”,“编剧”:“黑泽明(剧本)”,“桥本真武(剧本)”,“演员”:“ToshirôMifune,Takashi Shimura,Keiko Tsushima,Yukiko Shimazaki”,“阴谋”:“一个遭受土匪袭击的贫穷村庄招募了七名失业武士帮助他们自卫”,“语言”:“日语”,“国家”:“日本”,“奖项”:“提名2项奥斯卡奖。另外5项获奖和6项提名”,“海报”:”https://images-na.ssl-images-amazon.com/images/M/MV5BMTc5MDY1MjU5MF5BMl5BanBnXkFtZTgwNDM2OTE4MzE@“元分数”:“98”,“imdbRating”:“8.7”,“imdbvoces”:“238165”,“imdbID”:“tt0047478”,“Type”:“movie”,“Response”:“True”};
风险值递延=[];
var newData=[];
$(函数($){
var dt=$(“#示例”).DataTable({
columnDefs:[{目标:[0,-1],宽度:“150px”}],
栏目:[
{数据:“imdbID”},
{数据:“标题”},
{“数据”:“年份”}
],
正在加载:0,
对,,
“订单”:[[1,“asc”],
ajax:函数(数据、cb、设置){
//从嵌入的html获取DataTables创建的ID列表
var curData=$(“#示例”).DataTable().rows().data();
//如果您不清除,您将以双条目结束
$(“#示例”).DataTable().clear();
$.each(curData,function(i,item){
var sr={i:item.imdbID,plot:“short”,r:“json”,“番茄”:true};
推(
$.get(”http://www.omdbapi.com/“,sr)
.然后(功能(响应){
//将响应推送到全局数组中
newData[newData.length]=响应;
})
);
});
//现在进行所有调用。完成后,使用回调返回数据并填充表
$.when.apply(空,延迟)
.done(函数(){
cb({data:newData})
});
}
});
});

为什么不先获取数据,然后按照Peter Chon的建议构建表,或者使用作为DataTable api一部分的ajax?是的,rowCallback只对可见数据运行。因此,即使有一百万条记录,api调用也会受到限制,正如您在这里看到的,api只运行10倍:@Bindrid anot她的原因是,在我构建数据表之前,我不知道什么时候会返回api响应,这可能需要很多不可预测的时间。第一列中ID的原始来源是什么?如果将服务器端设置为true,则可以使用data:function(parm){}获取当前页面的ID并立即获取可见ID的所有数据。@Bindrid初始数据来自基本节点服务器,并注入ejs(嵌入式js)在html表中。恐怕我不明白你的建议,你有例子吗?这是可行的,但有两个问题:1)如果我有一百万行,它将发出一百万个api调用。你知道如何仅对可见行执行此操作吗?2)我如何知道所有api调用何时完成以运行datatable?好吧,根据你正在编写的原始代码对每个ID的调用。因此我不知道该怎么说。通常,我们会进行调用,然后根据返回的对象创建整个表。您的情况的问题是,您正在动态追加数据,因此.DataTable()不知道要排序什么。这很有效。谢谢!(我丢失了惰性加载,但是,我需要为此找到一些东西。)如果您希望能够对所有列中的列进行排序,您将放弃延迟加载。如果您愿意放弃搜索和排序功能,您可以一次引入数据页。不幸的是,您的选项是有限的,因为您使用的是omdbapi接口,并且它们的选项相当有限。
$('#example').find('tbody tr').each(customFnRowCallback);

function customFnRowCallback()
{
  var $this = $(this);
  var imdbID = $this.find('td:eq(0)').text();

  fetch("http://www.omdbapi.com/?i="+imdbID+"&plot=short&r=json&tomatoes=true")
  .then(function(response) {
    return response.json();
  })
  .then(function(json) {
    $this.find('td:eq(1)').text( json.Title );
  })
  .then(function() {
    $('#example').DataTable();
  })
  .catch(function(error) {
    console.log('There has been a problem with your fetch operation: ' + error.message);
  });
}
<script type="text/javascript">
    // Sample return set  from 
    var sampleReturn = { "Title": "Seven Samurai", "Year": "1954", "Rated": "UNRATED", "Released": "19 Nov 1956", "Runtime": "207 min", "Genre": "Adventure, Drama", "Director": "Akira Kurosawa", "Writer": "Akira Kurosawa (screenplay), Shinobu Hashimoto (screenplay), Hideo Oguni (screenplay)", "Actors": "Toshirô Mifune, Takashi Shimura, Keiko Tsushima, Yukiko Shimazaki", "Plot": "A poor village under attack by bandits recruits seven unemployed samurai to help them defend themselves.", "Language": "Japanese", "Country": "Japan", "Awards": "Nominated for 2 Oscars. Another 5 wins & 6 nominations.", "Poster": "https://images-na.ssl-images-amazon.com/images/M/MV5BMTc5MDY1MjU5MF5BMl5BanBnXkFtZTgwNDM2OTE4MzE@._V1_SX300.jpg", "Metascore": "98", "imdbRating": "8.7", "imdbVotes": "238,165", "imdbID": "tt0047478", "Type": "movie", "Response": "True" };
    var deferreds = [];
    var newData = [];
    $(function ($) {
        var dt = $("#example").DataTable({
            columnDefs:[{targets:[0, -1], width:"150px"}],
            columns: [
                { data: "imdbID" },
                { data: "Title" },
                { "data": "Year" }
            ],
            deferLoading: 0,
            deferRendering: true,
            "order": [[ 1, "asc" ]],
            ajax: function (data, cb, setting) {
                // get the list of ids created by DataTables from the embedded html
                var curData = $("#example").DataTable().rows().data();
                // if you don't clear, you will end up with double entries
                $("#example").DataTable().clear();
                $.each(curData, function (i, item) { 
                    var sr = { i: item.imdbID, plot:"short", r:"json", "tomatoes":true};
                    deferreds.push(
                    $.get("http://www.omdbapi.com/", sr)
                    .then(function (response) {
                        // push the response into the global array
                        newData[newData.length] = response;
                    })
                );
                });

                // now make all of the calls. When done, use the callback to return the data and populate the table
                $.when.apply(null, deferreds)
                   .done(function () {
                       cb({ data: newData })
                 });
            }
        });
    });
</script>