Mecha versi 2.6.4 sudah dirilis!

Pilih Mana: Memuat JSON Blogger dengan Metode Tradisional atau dengan Metode AJAX?

Terdapat dua metode untuk memuat data JSON Blogger dengan JavaScript. Setiap metode memiliki kekurangan dan kelebihannya masing-masing.

Tabel Konten
  1. Metode Tradisional 
  2. Metode AJAX 

Menambahkan parameter alt dengan nilai json atau json-in-script pada URL umpan blog akan memberikan hasil keluaran data berupa JSON. Pengembang bisa memanfaatkan data tersebut untuk membuat gawai blog. Namun untuk bisa memproses data, kita perlu menemukan cara untuk menampung data tersebut ke dalam parameter fungsi:

function recentPosts(json) {
    // Ubah data `json` menjadi gawai di sini…
}

recentPosts( /* Masukan data JSON di sini… */ );

Metode Tradisional 

Blogger memberikan akses kepada para pengembang untuk memproses data yang diberikan melalui parameter callback. Dengan menyatakan nama fungsi pada parameter tersebut, maka hasil keluaran JSON mentah yang diberikan akan dilengkapi dengan kode eksekusi fungsi yang membungkus data JSON tersebut. Sebenarnya tidak ada hal yang ajaib dalam sistem pemuatan data seperti itu. Tanpa parameter callback, hasil keluaran yang akan diberikan adalah seperti ini:

{
  "version": "1.0",
  "encoding": "UTF-8",
  "feed": { … }
}

Sedangkan ketika menggunakan parameter callback dengan nilai recentPosts, maka hasil keluaran yang akan diberikan adalah seperti ini:

recentPosts({
  "version": "1.0",
  "encoding": "UTF-8",
  "feed": { … }
});

Sehingga ketika umpan blog berhasil dimuat, maka data yang akan termuat bukan hanya terdiri dari JSON saja tetapi juga fungsi global yang memproses data JSON tersebut pada saat yang bersamaan ketika JSON termuat:

<!-- Tanpa eksekusi fungsi -->
<script src="/feeds/posts/summary?alt=json"></script>

<!-- Dengan eksekusi fungsi -->
<script src="/feeds/posts/summary?alt=json&amp;callback=recentPosts"></script>

Menerapkan metode seperti ini bukan berarti tidak memiliki kekurangan. Karena umpan blog perlu menerima nama fungsi yang bersifat global, maka kita harus mengaitkan fungsi gawai yang kita buat pada objek window. Satu-satunya cara yang bisa kita lakukan adalah dengan mendeklarasikan fungsi tersebut pada bagian terluar dari berkas JavaScript, atau dengan mendeklarasikan fungsi tersebut sebagai salah satu properti dari window jika fungsi tersebut berada di dalam fungsi-fungsi yang lain:

// Metode 1
function recentPosts(json) { … }

// Metode 2
window.recentPosts = function(json) { … };

// Metode 3
(function(w) {
    w.recentPosts = function(json) { … };
})(window);

// Metode 4
function start() {
    function createRecentPostsFunction() {
        function a() { … }
        function b() { … }
        function c() {
            window.recentPosts = function(json) { … };
        }
        a();
        b();
        c();
    }
    function hasRecentPostsFunction() {
        return 'recentPosts' in window && 'function' === typeof window.recentPosts;
    }
    if (!hasRecentPostsFunction()) {
        createRecentPostsFunction();
    }
}

start();

Karena JavaScript memungkinkan kita untuk menimpa fungsi yang telah dibuat sebelumnya dengan cara membuat fungsi yang baru (atau membuat variabel) menggunakan nama yang sama, maka akan sangat mudah bagi fungsi tersebut untuk mengalami konflik-konflik penamaan seperti ini:

<!-- Kode pihak ke 1 (kamu) -->
<script>
function recentPosts(json) { … }
</script>

<!-- Kode pihak ke 3 (orang lain) yang akan merusak fungsi `recentPosts()` -->
<script>
var recentPosts = null;
</script>

<!-- Di sini akan muncul pesan kesalahan “TypeError: recentPosts is not a function” -->
<script src="/feeds/posts/summary?alt=json&amp;callback=recentPosts"></script>

Ada dua cara yang dapat kamu lakukan untuk menghindari masalah tersebut. Cara yang pertama adalah dengan mendeklarasikan fungsi recentPosts sebagai konstanta agar nama fungsi tersebut tidak bisa digunakan lagi di tempat lain setelah konstanta tersebut dinyatakan:

<script>
const recentPosts = json => { … };
</script>

<!-- Akan muncul pesan kesalahan “SyntaxError: redeclaration of const recentPosts” -->
<script>
function recentPosts(json) { … };
</script>

<!-- Akan muncul pesan kesalahan “SyntaxError: redeclaration of const recentPosts” -->
<script>
let recentPosts = json => { … };
</script>

<!-- Akan muncul pesan kesalahan “SyntaxError: redeclaration of const recentPosts” -->
<script>
const recentPosts = json => { … };
</script>

Cara yang ke dua adalah dengan membuat nama fungsi yang tidak permanen dan bersifat acak. Cara di bawah ini memungkinkan kita untuk membuat fungsi global yang bisa berubah-ubah namanya setiap kali halaman dimuat, sehingga akan memperkecil kemungkinan pihak lain untuk mendeklarasikan fungsi gawai dengan nama yang sama:

let id = Math.floor(Math.random() * 1000),
    node = document.createElement('script');

window['recentPosts_' + id] = json => { … };

node.src = '/feeds/posts/summary?alt=json&callback=recentPosts_' + id;

document.head.appendChild(node);

Metode AJAX 

Memuat data menggunakan AJAX relatif lebih praktis, walaupun dari segi sintaks mungkin akan terlihat rumit bagi orang-orang yang belum terbiasa. Kamu bisa menggunakan fungsi ini sebagai contekan selama kamu masih belum menguasai konsep AJAX. Dengan menggunakan AJAX, kamu tidak perlu menambahkan parameter callback karena data yang dimuat nantinya akan secara otomatis tertampung ke dalam parameter fungsi untuk menyatakan kesuksesan proses pemuatan data. Kamu bisa menggunakan XMLHttpRequest atau fetch. Pilih salah satu:

let xhr = new XMLHttpRequest;

// Buka tautan umpan dengan metode `GET`
xhr.open('GET', '/feeds/posts/summary?alt=json', true);

// Atur tipe respons sebagai JSON, bukan teks
xhr.responseType = 'json';

// Proses manipulasi data dilakukan di dalam acara `readystate`
xhr.addEventListener('readystate', function() {
    if (4 === this.readyState && 200 === this.status) {
        let json = this.response;
        // Ubah data `json` menjadi gawai mulai dari sini…
    }
}, false);

// Memulai permintaan data!
xhr.send();
// Memulai permintaan data!
fetch('/feeds/posts/summary?alt=json').then(response => {
    return response.json(); // Atur tipe respons sebagai JSON, bukan teks
}).then(json => {
    // Ubah data `json` menjadi gawai mulai dari sini…
});

Pakai jQuery juga bisa! Tapi akhir-akhir ini jQuery sudah ketinggalan zaman:

$.ajax({
    type: 'GET',
    url: '/feeds/posts/summary?alt=json',
    dataType: 'json'
}).done(function(json) {
    // Ubah data `json` menjadi gawai di sini…
});
$.get('/feeds/posts/summary?alt=json', function(json) {
    // Ubah data `json` menjadi gawai di sini…
}, 'json');

Mengeksekusi fungsi recentPosts() melalui respons AJAX dapat dilakukan dengan cara seperti ini:

xhr.addEventListener('readystate', function() {
    if (4 === this.readyState && 200 === this.status) {
        recentPosts(this.response);
    }
}, false);
fetch('/feeds/posts/summary?alt=json').then(response => response.json()).then(recentPosts);
$.ajax({
    type: 'GET',
    url: '/feeds/posts/summary?alt=json',
    dataType: 'json'
}).done(recentPosts);
$.get('/feeds/posts/summary?alt=json', recentPosts, 'json');

Kelebihan dari menggunakan metode AJAX adalah kamu tidak diharuskan untuk membuat fungsi gawai sebagai fungsi yang bersifat global, sehingga akan lebih ramah bagi lingkungan di luar gawai, serta dapat membebaskan fungsi tersebut dari kemungkinan-kemungkinan terjadinya konflik penamaan fungsi seperti yang telah Saya jelaskan sebelumnya pada metode pemuatan data umpan secara tradisional. Nama fungsi juga dapat dikompres dengan alat pengompres JavaScript tanpa memberikan pengaruh apa-apa pada hasil keluarannya:

(function() {
    function recentPosts(json) { … }
    fetch('/feeds/posts/summary?alt=json').then(response => response.json()).then(recentPosts);
})();

// Akan muncul pesan kesalahan “ReferenceError: recentPosts is not defined”
console.log(recentPosts);

Setiap metode tentu memiliki kekurangan dan kelebihannya masing-masing. Beberapa hal yang sudah Saya jabarkan di sini hanyalah sebagian kecilnya saja. Selebihnya mungkin dapat dijelaskan dengan contoh kasus. Jadi, mau pilih yang mana?

37 Komentar

Igniel

Saya tim ajax.

Riedayme

ada mba igniel comment, unblock dong mba hehe \o/

Riedayme

mantap saya blm pernah coba yang ajax. siapa tau nanti bisa dicoba

Hhhmmzz!

apa nama/fungsi Javascript yang Mas pakai di blog ini? Maksud saya seperti di halaman homepage, ketika saya meng-click dengan cara ctrl+click yang seharusnya terbuka di tab baru tapi nyatanya tidak.

Taufik Nurrohman

Rasa-rasanya Saya nggak ngelakuin apa-apa ke perilaku tersebut. Mungkin itu hasil efek samping dari tautan AJAX, karena semua tautan lokal di blog ini sudah dimatikan dan perpindahan lokasi sudah digantikan tugasnya oleh JavaScript.

Anonim

enak ajax

Sumirat

Pengguna jquery mundur dulu :(

Azim Muqtadi

Untuk script AJAX ini saya bisa pakai untuk manggil data JSON Google Spredsheet enggak bro?

Taufik Nurrohman

Bisa mas, soalnya ini natif. Cuma kalau URL target tidak mendukung penambahan fungsi global melalui parameter callback misalnya, kita hanya bisa menggunakan yang versi fetch atau XMLHttpRequest saja.

Adi

Halo mas, saya ingin tanya kalau json yang seperti ini bagaimana caranya agar bisa ditampilkan "origin, destination, dll", menggunakan cara yang seperti related post atau ajax. Saya bingung karena terkadang berubah-ubah "LAX,MOW,dll". Oh ya pertanyaan saya yang sebelumnya akhirnya saya sudah bisa caranya agar bisa sesuai kota pengunjung websitenya.

{
    "success": true,
    "data": {
        "LAX": {....},
        "MOW": {...},
        "LON": {....},
        "LAS": {....},
        "FLL": {....},
        "MIA": {
            "origin": "NYC",
            "destination": "MIA",
            "price": 217,
            "airline": "AA"
        }
    },
    "currency": "usd"
}

Taufik Nurrohman

Pakai kondisional untuk mengecek adanya properti.

if (typeof json.data.LAX !== 'undefined' && typeof json.data.MOW !== 'undefined') {
    // asdf
}

Adi

Kalau JSON-nya memakai token apakah hanya bisa memakai metode fetch saja mas?

Seperti ini kode saya masih percobaan, tapi masih belum bisa saya:

fetch(`https://api.allorigins.win/get?url=${encodeURIComponent('https://suggest.travelpayouts.com/v1/city-directions?origin=NYC&currency=usd&limit=6&token=11f5bcc5ceea8531830e84d8d3baebf8')}`)
    .then(response => {
        return response.json();
    })
    .then(data => {
        console.log(data);
        data.forEach(user => {
            output += `
                <ul>
                    <li>${user.data.origin}</li>
                    <li>${user.data.destination}</li>
                    <li>${user.data.price}</li>
                </ul>
            `;
        })
        document.getElementById('output').innerHTML = output;
    });

Taufik Nurrohman

[…] apakah hanya bisa memakai metode fetch saja mas?

Kalau token berada di URL nggak selalu harus pakai AJAX. Kecuali kalau data token harus dikirim melalui HTTP headers, atau harus dikirim menggunakan metode POST.

Di kodemu variabel output belum dinyatakan tapi sudah keburu di += kan. Coba nyatakan dulu variabel output sebelum data.forEach()

let output = "";
data.forEach(user => { … });

Adi

Di dokumentasi mereka mengatakan kalau "Permintaan Ajax ke API tidak berfungsi karena token akses diteruskan tidak terenkripsi, dan harus membuat permintaan ke API dari server."

Apa itu karena masalah cors mas?

Saya mencoba menggunakan cloudflare workers untuk membuat apinya bisa diakses menggunakan domain saya sendiri seperti ini https://www.travellingticket.com/api/v1/city-directions?origin=NYC&currency=usd&limit=6&token=11f5bcc5ceea8531830e84d8d3baebf8

Kalau yang let output belum saya coba. saya ada pertanyaan lainnya kalau jsonnya tidak menyediakan callback apa masih bisa di jalankan mas?

Adi

Mas kalau seperti ini apa sudah benar penulisan kodenya

if (datax.type == "airport") {
    id_location = datax.id;
    name_location = datax.name;
    break;
}

saya ingin mengambil data yang ada type airport saja.

[{"iata":"","name":"Surabaya Airport","id":"3918703","type":"airport"},{"iata":"","name":"Surabaya Downtown","id":"3918702","type":"other"},{"iata":"","name":"Surabaya - Wonorejo","id":"4026995","type":"other"}]

Taufik Nurrohman

break tidak berlaku di dalam .forEach(). Coba begini:

data.filter(v => v.type === 'airport').forEach(v => {
    id_location = v.id;
    name_location = v.name;
});

Adi

oh ya mas, kalau misalnya type airportnya ada lebih dari satu dan ingin pilih yang urutan yang pertama bagaimana ya mas?

Adi

kalau tentang yang ini, mungkin seperti cara ini mas https://www.sitepoint.com/community/t/369576/3 tapi dia menggunakan fetch, kalau jquery bagaiamana caranya mas?

{
    "success": true,
    "data": {
        "LAX": {....},
        "MOW": {...},
        "LON": {....},
        "LAS": {....},
        "FLL": {....},
        "MIA": {
            "origin": "NYC",
            "destination": "MIA",
            "price": 217,
            "airline": "AA"
        }
    },
    "currency": "usd"
}

Adi

Sepertinya untuk API travelpayouts saya menggunakan layanan rapidapi yang gratis. Jadi file jsonnya bisa saya pakai.

Adi

Mas saya ingin mengubah angka menjadi bintang tapi kenapa hanya hanya 1 kolom saja yang menampilkan bintangnya, kolom lainnya tidak tampil.

$.ajax({
    url: "",
    success: function(data) {
        var blockbody = '';
        for (var i = 0; i < data.tophotels.length; i++) {
            var stars = data.tophotels[i].stars;
            blockbody += "" + stars + "";
        }
        blockbody += '';
        document.getElementById('hotelnearme').innerHTML = blockbody;
        document.getElementById("bintang").innerHTML = getStars(stars);
        function getStars(a) {
            a = Math.round(2 * a) / 2;
            for (var b = [], c = a; 1 <= c; c--) b.push('<i class="icon-star"></i>');
            .5 == c && b.push('<i class="icon-star-half"></i>');
            for (a = 5 - a; 1 <= a; a--) b.push('<i class="icon-star-o"></i>');
            return b.join("");
        }
    }
});

Adi

Oh saya sudah bisa mas.

Adi

Mas, saya ingin menampilkan nama kota yang semulanya hanya iata-nya saja menjadi nama kota aslinya, tapi malah hanya satu kota saja yang muncul disemua kotak kolomnya?

$.ajax(matrix).done(function(datax) {
    for (var i = 0; i < datax.data.length; i++) {
        var origin = datax.data[i].origin;
        $.ajax({
            url: "https://autocomplete.travelpayouts.com/places2?term=" + origin + "&locale=en_us&types=city%2Cairport&max=1",
            type: 'get',
            dataType: "jsonp",
            success: function(data) {
                for (var i = 0; i < data.length; i++) {
                    asal = data[i].name;
                    console.log(asal);
                    $.ajax(settings).done(function(response) {
                        var blockbody = '<div class="row no-gutters">';
                        for (var i = 0; i < response.data.length; i++) {
                            var origin = response.data[i].origin;
                            blockbody += "<span>" + asal + ",</span>";
                        }
                        blockbody += '</div>';
                        document.getElementById('flights').innerHTML = blockbody;
                    });
                }
            }
        });
    }
});

Taufik Nurrohman

Variabel i harus diganti dengan nama yang lain pada iterasi-iterasi berikutnya:

for (var i = 0, j = /* … */; i < j; i++) {
    for (var ii = 0, jj = /* … */; ii < ji; ii++) {
        for (var iii = 0, jjj = /* … */; iii < jjj; iii++) {
            /* … */
        }
    }
}

Adi

apa seperti ini mas?

$.ajax(matrix).done(function(datax) {
    for (var i = 0, j = datax.data.length; i < j; i++) {
        var origin = datax.data[i].origin;
        $.ajax({
            url: "https://autocomplete.travelpayouts.com/places2?term=" + origin + "&locale=en_us&types=city%2Cairport&max=1",
            type: 'get',
            dataType: "jsonp",
            success: function(data) {
                for (var ii = 0, jj = data.length; ii < ji; ii++) {
                    asal = data[i].name;
                    console.log(asal);
                    $.ajax(settings).done(function(response) {
                        var blockbody = '<div class="row no-gutters">';
                        for (var iii = 0, jjj = response.data.length; iii < jjj; iii++) {
                            var origin = response.data[i].origin;
                            blockbody += "<span>" + asal + ",</span>";
                        }
                        blockbody += '</div>';
                        document.getElementById('flights').innerHTML = blockbody;
                    });
                }
            }
        });
    }
});

postkomik

Mas kalo memfilter label tertentu dan data nya dari json gimana contoh funsi nya ?

Adi

Halo Mas, ini kenapa ya mas saya mau menambahkan headers pada jquery autocomplete tapi kok masih unauthorized

$.ajax({
                url: 'https://viator-autocomplete.p.rapidapi.com/orion/ajax/react/typeahead?',
                data: {
                    text: request.term
                },
                method: "GET",
                headers: {
        "x-rapidapi-host": "viator-autocomplete.p.rapidapi.com",
        "x-rapidapi-key": "7553c9c4b0msh01b4944e1049a81p158876jsn340bfdd90264"
    },
                async: "true",
                crossDomain: "true",
                dataType: "jsonp",
                success: function(data) {

                }
            });
        },

Taufik Nurrohman

Saya butuh tautan dokumentasi sama hasil respons untuk bisa bantu.

Adi

kalau untuk dokumentasi autocomplete di rapidAPI sepertinya tidak ada mas dan untuk hasil respons kalau dipakai biasa tidak ada masalah, hanya seperti ini kode yang mereka berikan untuk versi jquery.

const settings = {
    "async": true,
    "crossDomain": true,
    "url": "https://viator-autocomplete.p.rapidapi.com/orion/ajax/react/typeahead?text=Surabaya",
    "method": "GET",
    "headers": {
        "x-rapidapi-host": "viator-autocomplete.p.rapidapi.com",
        "x-rapidapi-key": "7553c9c4b0msh01b4944e1049a81p158876jsn340bfdd90264"
    }
};

$.ajax(settings).done(function (response) {
    console.log(response);
});

bedanya pakai ".done" dengan "success:" itu apa mas?

Taufik Nurrohman

Properti success: diimplementasikan pada jQuery versi lama, sebelum API Promise keluar. Setelah fitur async/await didukung di semua peramban mayor, banyak pengembang JavaScript memutuskan untuk mengimplementasikannya. .fail() dan .done() pada jQuery.ajax() itu setara dengan .catch() dan .then() pada fetch().

Adi

oh ternyata saya yang salah mas, seharusnya menggunakan dataType: "json", bukan pakai dataType: "jsonp",

dan mungkin pakai ini juga contentType: "application/json; charset=utf-8",

Adi

mas kalau json nya seperti ini, apa benar penulisan kode autocomplatenya seperti ini?

{
  "cities":  [...],
  "hotels": [...]
}
response($.map(data.hotels, function(v, i) {
    return {...}
}));
response($.map(data.cities, function(v, i) {
    return {...}
}));

Taufik Nurrohman

Apa itu response()?

Adi

contohnya seperti ini mas

$(document).ready(function() {
$("input#hotel_").autocomplete({
        minLength: 2,
        source: function(request, response) {
            $.ajax({
                url: 'https://yasen.hotellook.com/autocomplete?lang=en-US&limit=5',
                data: {
                    term: request.term
                },
                dataType: "jsonp",
                success: function(data) {
                    response($.map(data.hotels, function(v, i) {
                        return {
                            label: v.name,
                            value: v.locationId,
                            code: v.id,
                            name: v.name,
                            icon: "la-hotel"
                        }

                    }));
                    response($.map(data.cities, function(v, i) {
                        return {
                            label: v.city + ", " + v.country,
                            value: v.id,
                            code: v.iata[0],
                            name: v.hotelsCount + " Hotels",
                            icon: "la-city"
                        }
                    }));
                }
            });
        },
        focus: function(event, ui) {
            event.preventDefault();
            $(this).val(ui.item.label);
        },
        select: function(event, ui) {
            event.preventDefault();
            $(this).val(ui.item.label);
            $("input#hotel_").val(ui.item.label);
            $("input#cityId").val(ui.item.value);
        }
    }).data("ui-autocomplete")._renderItem = function(ul, item) {
        $div = $("<div class='la " + item.icon + "'></div><div class='ui-menu-item-wrapper item_menu_autocomplete'>" + item.label + "<p class='ui-menu-item-text'>" + item.code + "</p></div><span class='ui-menu-item-iata'>" + item.name + "</span>");
        return $("<li></li>").append($div).appendTo(ul);
    };
});

Taufik Nurrohman

Iya bisa. Sudah jadi kan?

Adi

belum bisa mas, cara seperti itu hanya bisa menampilkan yang ini saja

{
"hotels": [...]
}

Taufik Nurrohman

Supaya lebih mudah dalam pengecekan, selalu lakukan console.log(v, k) sebelum return.

Komentar telah ditutup.