Cara menggunakan javascript promise

Mari kembali ke masalah yang disebutkan di dalam bab Pengenalan: callback: kita memiliki sebuah urutan tugas asynchronous untuk dilakukan satu demi satu. Sebagai contoh, memuat scripts. Bagaimana kita bisa membuat kodenya dengan baik?

Promises menyediakan beberapa resep untuk melakukannya.

Di bab ini kita melibatkan promise chaining.

Itu terlihat seperti ini:

new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000); // (*)
})
  .then(function (result) {
    // (**)

    alert(result); // 1
    return result * 2;
  })
  .then(function (result) {
    // (***)

    alert(result); // 2
    return result * 2;
  })
  .then(function (result) {
    alert(result); // 4
    return result * 2;
  });

Idenya adalah bahwa result diteruskan melalui rantai handlers

let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
3.

Ini alurnya:

  1. Promise pertama selesai dalam 1 detik
    let promise = new Promise(function (resolve, reject) {
      setTimeout(() => resolve(1), 1000);
    });
    
    promise.then(function (result) {
      alert(result); // 1
      return result * 2;
    });
    
    promise.then(function (result) {
      alert(result); // 1
      return result * 2;
    });
    
    promise.then(function (result) {
      alert(result); // 1
      return result * 2;
    });
    4,
  2. Kemudian handler
    let promise = new Promise(function (resolve, reject) {
      setTimeout(() => resolve(1), 1000);
    });
    
    promise.then(function (result) {
      alert(result); // 1
      return result * 2;
    });
    
    promise.then(function (result) {
      alert(result); // 1
      return result * 2;
    });
    
    promise.then(function (result) {
      alert(result); // 1
      return result * 2;
    });
    3 dipanggil
    let promise = new Promise(function (resolve, reject) {
      setTimeout(() => resolve(1), 1000);
    });
    
    promise.then(function (result) {
      alert(result); // 1
      return result * 2;
    });
    
    promise.then(function (result) {
      alert(result); // 1
      return result * 2;
    });
    
    promise.then(function (result) {
      alert(result); // 1
      return result * 2;
    });
    6.
  3. Nilai yang dikembalikan diteruskan ke handler
    let promise = new Promise(function (resolve, reject) {
      setTimeout(() => resolve(1), 1000);
    });
    
    promise.then(function (result) {
      alert(result); // 1
      return result * 2;
    });
    
    promise.then(function (result) {
      alert(result); // 1
      return result * 2;
    });
    
    promise.then(function (result) {
      alert(result); // 1
      return result * 2;
    });
    3 selanjutnya
    let promise = new Promise(function (resolve, reject) {
      setTimeout(() => resolve(1), 1000);
    });
    
    promise.then(function (result) {
      alert(result); // 1
      return result * 2;
    });
    
    promise.then(function (result) {
      alert(result); // 1
      return result * 2;
    });
    
    promise.then(function (result) {
      alert(result); // 1
      return result * 2;
    });
    8
  4. …dan seterusnya.

Selama result diteruskan di sepanjang rantai handlers, kita bisa melihat urutan pemanggilan

let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
9:
new Promise(function(resolve, reject) {

  setTimeout(() => resolve(1), 1000);

}).then(function(result) {

  alert(result); // 1

  return new Promise((resolve, reject) => { // (*)
    setTimeout(() => resolve(result * 2), 1000);
  });

}).then(function(result) { // (**)

  alert(result); // 2

  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(result * 2), 1000);
  });

}).then(function(result) {

  alert(result); // 4

});
0 →
new Promise(function(resolve, reject) {

  setTimeout(() => resolve(1), 1000);

}).then(function(result) {

  alert(result); // 1

  return new Promise((resolve, reject) => { // (*)
    setTimeout(() => resolve(result * 2), 1000);
  });

}).then(function(result) { // (**)

  alert(result); // 2

  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(result * 2), 1000);
  });

}).then(function(result) {

  alert(result); // 4

});
1 →
new Promise(function(resolve, reject) {

  setTimeout(() => resolve(1), 1000);

}).then(function(result) {

  alert(result); // 1

  return new Promise((resolve, reject) => { // (*)
    setTimeout(() => resolve(result * 2), 1000);
  });

}).then(function(result) { // (**)

  alert(result); // 2

  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(result * 2), 1000);
  });

}).then(function(result) {

  alert(result); // 4

});
2.

Seluruhnya bekerja, karena pemanggilan ke

new Promise(function(resolve, reject) {

  setTimeout(() => resolve(1), 1000);

}).then(function(result) {

  alert(result); // 1

  return new Promise((resolve, reject) => { // (*)
    setTimeout(() => resolve(result * 2), 1000);
  });

}).then(function(result) { // (**)

  alert(result); // 2

  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(result * 2), 1000);
  });

}).then(function(result) {

  alert(result); // 4

});
3 mengembalikan sebuah promise, jadi kita bisa memanggil
let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
3 selanjutnya.

Ketika sebuah handler mengembalikan nilai, handler tersebut menjadi hasil dari promise, jadi

let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
3 selanjutnya dipanggil dengan itu.

Kesalahan klasik pemula: secara teknis kita juga dapat menambahkan banyak

let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
3 ke satu promise. Ini bukan chaining.

Sebagai contoh:

let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

Apa yang kita lakukan di sini hanya beberapa handlers untuk satu promise. Handlers tersebut tidak meneruskan result ke satu sama lain, melainkan memprosesnya masing-masing.

Ini gambarnya (bandingkan dengan chaining di atas):

Semua

let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
3 pada promise yang sama mendapatkan result yang sama – result dari promise. Jadi di dalam kode di atas semua
let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
9 menunjukkan yang sama:
new Promise(function(resolve, reject) {

  setTimeout(() => resolve(1), 1000);

}).then(function(result) {

  alert(result); // 1

  return new Promise((resolve, reject) => { // (*)
    setTimeout(() => resolve(result * 2), 1000);
  });

}).then(function(result) { // (**)

  alert(result); // 2

  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(result * 2), 1000);
  });

}).then(function(result) {

  alert(result); // 4

});
0.

Dalam prakteknya kita jarang membutuhkan banyak handlers untuk satu promise. Chaining lebih sering digunakan.

Sebuah handler, yang digunakan di dalam

loadScript("/article/promise-chaining/one.js")
  .then(function (script) {
    return loadScript("/article/promise-chaining/two.js");
  })
  .then(function (script) {
    return loadScript("/article/promise-chaining/three.js");
  })
  .then(function (script) {
    // gunakan functions yang dideklarasikan di dalam scripts
    // untuk menunjukkan bahwa functions memang dimuat
    one();
    two();
    three();
  });
0 dapat membuat dan mengambalikan sebuah promise.

Dalam hal ini handlers selanjutnya menunggu sampai mengendap, dan kemudian mendapatkan hasilnya.

Sebagai contoh:

new Promise(function(resolve, reject) {

  setTimeout(() => resolve(1), 1000);

}).then(function(result) {

  alert(result); // 1

  return new Promise((resolve, reject) => { // (*)
    setTimeout(() => resolve(result * 2), 1000);
  });

}).then(function(result) { // (**)

  alert(result); // 2

  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(result * 2), 1000);
  });

}).then(function(result) {

  alert(result); // 4

});

Di sini

let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
3 pertama menunjukan
new Promise(function(resolve, reject) {

  setTimeout(() => resolve(1), 1000);

}).then(function(result) {

  alert(result); // 1

  return new Promise((resolve, reject) => { // (*)
    setTimeout(() => resolve(result * 2), 1000);
  });

}).then(function(result) { // (**)

  alert(result); // 2

  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(result * 2), 1000);
  });

}).then(function(result) {

  alert(result); // 4

});
0 dan mengembalikan
loadScript("/article/promise-chaining/one.js")
  .then(function (script) {
    return loadScript("/article/promise-chaining/two.js");
  })
  .then(function (script) {
    return loadScript("/article/promise-chaining/three.js");
  })
  .then(function (script) {
    // gunakan functions yang dideklarasikan di dalam scripts
    // untuk menunjukkan bahwa functions memang dimuat
    one();
    two();
    three();
  });
3 pada baris
let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
4. Setelah satu detik selesai, dan hasil (argument
loadScript("/article/promise-chaining/one.js")
  .then(function (script) {
    return loadScript("/article/promise-chaining/two.js");
  })
  .then(function (script) {
    return loadScript("/article/promise-chaining/three.js");
  })
  .then(function (script) {
    // gunakan functions yang dideklarasikan di dalam scripts
    // untuk menunjukkan bahwa functions memang dimuat
    one();
    two();
    three();
  });
5, di sini
loadScript("/article/promise-chaining/one.js")
  .then(function (script) {
    return loadScript("/article/promise-chaining/two.js");
  })
  .then(function (script) {
    return loadScript("/article/promise-chaining/three.js");
  })
  .then(function (script) {
    // gunakan functions yang dideklarasikan di dalam scripts
    // untuk menunjukkan bahwa functions memang dimuat
    one();
    two();
    three();
  });
6) diteruskan ke handler
let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
3 kedua. Handler pada baris
let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
6, menunjukan
new Promise(function(resolve, reject) {

  setTimeout(() => resolve(1), 1000);

}).then(function(result) {

  alert(result); // 1

  return new Promise((resolve, reject) => { // (*)
    setTimeout(() => resolve(result * 2), 1000);
  });

}).then(function(result) { // (**)

  alert(result); // 2

  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(result * 2), 1000);
  });

}).then(function(result) {

  alert(result); // 4

});
1 dan melakukan hal yang sama.

Jadi keluarannya sama dengan contoh sebelumnya: 1 → 2 → 4, tetapi sekarang dengan menunda 1 detik antara pemanggilan

let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
9.

Mengembalikan promises memperbolehkan kita untuk membangun rantai aksi asynchronous.

Mari menggunakan fitur ini dengan promisified

loadScript("/article/promise-chaining/one.js")
  .then((script) => loadScript("/article/promise-chaining/two.js"))
  .then((script) => loadScript("/article/promise-chaining/three.js"))
  .then((script) => {
    // scripts dimuat, kita dapat menggunakan functions yang dideklarasikan di sini
    one();
    two();
    three();
  });
1, didefinisikan di , untuk memuat scripts satu demi satu, secara berurutan:

loadScript("/article/promise-chaining/one.js")
  .then(function (script) {
    return loadScript("/article/promise-chaining/two.js");
  })
  .then(function (script) {
    return loadScript("/article/promise-chaining/three.js");
  })
  .then(function (script) {
    // gunakan functions yang dideklarasikan di dalam scripts
    // untuk menunjukkan bahwa functions memang dimuat
    one();
    two();
    three();
  });

Kode ini bisa lebih ringkas dengan arrow functions:

loadScript("/article/promise-chaining/one.js")
  .then((script) => loadScript("/article/promise-chaining/two.js"))
  .then((script) => loadScript("/article/promise-chaining/three.js"))
  .then((script) => {
    // scripts dimuat, kita dapat menggunakan functions yang dideklarasikan di sini
    one();
    two();
    three();
  });

Di sini setiap pemanggilan

loadScript("/article/promise-chaining/one.js")
  .then((script) => loadScript("/article/promise-chaining/two.js"))
  .then((script) => loadScript("/article/promise-chaining/three.js"))
  .then((script) => {
    // scripts dimuat, kita dapat menggunakan functions yang dideklarasikan di sini
    one();
    two();
    three();
  });
1 mengembalikkan sebuah promise, dan
let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
3 selanjutnya berjalan ketika promise selesai. Kemudian memulai pemuatan script selanjutnya. Jadi scripts dimuat satu setelah yang lain.

Kita dapat menambahkan lagi aksi asynchronous ke rantainya. Harap catat bahwa kodenya masih “flat”, kodenya tumbuh ke bawah bukan ke kanan. Tidak ada tanda-tanda “pyramid of doom”.

Secara teknis, kita dapat menambahkan

let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
3 secara langsung ke setiap
loadScript("/article/promise-chaining/one.js")
  .then((script) => loadScript("/article/promise-chaining/two.js"))
  .then((script) => loadScript("/article/promise-chaining/three.js"))
  .then((script) => {
    // scripts dimuat, kita dapat menggunakan functions yang dideklarasikan di sini
    one();
    two();
    three();
  });
1, seperti ini:

loadScript("/article/promise-chaining/one.js").then((script1) => {
  loadScript("/article/promise-chaining/two.js").then((script2) => {
    loadScript("/article/promise-chaining/three.js").then((script3) => {
      // this function has access to variables script1, script2 and script3
      one();
      two();
      three();
    });
  });
});

Kode ini melakukan hal yang sama: muat 3 scripts berurutan. Tetapi “tumbuh ke kanan”. Jadi kita punya masalah yang sama dengan callbacks.

Orang yang baru memulai untuk menggunakan promises kadang-kadang tidak tahu tentang chaining, jadi mereka menulisnya dengan cara ini. Umumnya, chaining lebih disukai.

Terkadang ok untuk menulis

let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
3 secara langsung, karena function bersarang memiliki akses ke luar scope. Pada contoh di atas callback paling bertingkat memiliki akses ke semua variabel
loadScript("/article/promise-chaining/one.js")
  .then((script) => loadScript("/article/promise-chaining/two.js"))
  .then((script) => loadScript("/article/promise-chaining/three.js"))
  .then((script) => {
    // scripts dimuat, kita dapat menggunakan functions yang dideklarasikan di sini
    one();
    two();
    three();
  });
7,
loadScript("/article/promise-chaining/one.js")
  .then((script) => loadScript("/article/promise-chaining/two.js"))
  .then((script) => loadScript("/article/promise-chaining/three.js"))
  .then((script) => {
    // scripts dimuat, kita dapat menggunakan functions yang dideklarasikan di sini
    one();
    two();
    three();
  });
8,
loadScript("/article/promise-chaining/one.js")
  .then((script) => loadScript("/article/promise-chaining/two.js"))
  .then((script) => loadScript("/article/promise-chaining/three.js"))
  .then((script) => {
    // scripts dimuat, kita dapat menggunakan functions yang dideklarasikan di sini
    one();
    two();
    three();
  });
9. Tetapi itu pengecualian bukan aturan.

Thenables

Tepatnya, sebuah handler mungkin tidak mengembalikkan sebuah promise, tetapi dipanggil objek “thenable” – sebuah objek sewenang-wenang yang memiliki method

let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
3, dan diperlakukan sama seperti sebuah promise.

Idenya adalah bahwa pustaka 3rd-party dapat menerapkan objek “promise-compatible” mereka sendiri. Mereka dapat memiliki serangkaian methods yang luas, tetapi juga kompatibel dengan promises asli, karena mereka menerapkan

let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
3.

Ini contoh dari objek thenable:

class Thenable {
  constructor(num) {
    this.num = num;
  }
  then(resolve, reject) {
    alert(resolve); // function() { native code }
    // selesai dengan this.num*2 setelah 1 detik
    setTimeout(() => resolve(this.num * 2), 1000); // (**)
  }
}

new Promise(resolve => resolve(1))
  .then(result => {
    return new Thenable(result); // (*)
  })
  .then(alert); // menunjukkan 2 setelah 1000ms

JavaScript memeriksa objek yang dikembalikkan oleh handler

let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
3 di baris
let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
4: jika ada method callable yang bernama
loadScript("/article/promise-chaining/one.js").then((script1) => {
  loadScript("/article/promise-chaining/two.js").then((script2) => {
    loadScript("/article/promise-chaining/three.js").then((script3) => {
      // this function has access to variables script1, script2 and script3
      one();
      two();
      three();
    });
  });
});
4, kemudian method tersebut memanggil method yang menyediakan functions
loadScript("/article/promise-chaining/one.js")
  .then(function (script) {
    return loadScript("/article/promise-chaining/two.js");
  })
  .then(function (script) {
    return loadScript("/article/promise-chaining/three.js");
  })
  .then(function (script) {
    // gunakan functions yang dideklarasikan di dalam scripts
    // untuk menunjukkan bahwa functions memang dimuat
    one();
    two();
    three();
  });
5,
loadScript("/article/promise-chaining/one.js").then((script1) => {
  loadScript("/article/promise-chaining/two.js").then((script2) => {
    loadScript("/article/promise-chaining/three.js").then((script3) => {
      // this function has access to variables script1, script2 and script3
      one();
      two();
      three();
    });
  });
});
6 asli sebagai arguments (mirip ke eksekutor) dan menunggu sampai satu dari mereka dipanggil. Pada contoh di atas
loadScript("/article/promise-chaining/one.js").then((script1) => {
  loadScript("/article/promise-chaining/two.js").then((script2) => {
    loadScript("/article/promise-chaining/three.js").then((script3) => {
      // this function has access to variables script1, script2 and script3
      one();
      two();
      three();
    });
  });
});
7 dipanggil setelah 1 detik
let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
6. Kemudian result diteruskan ke bawah chain.

Fitur ini memperbolehkan kita untuk untuk mengintegrasikan objek kustom dengan promise chains tanpa memiliki pewarisan dari

loadScript("/article/promise-chaining/one.js").then((script1) => {
  loadScript("/article/promise-chaining/two.js").then((script2) => {
    loadScript("/article/promise-chaining/three.js").then((script3) => {
      // this function has access to variables script1, script2 and script3
      one();
      two();
      three();
    });
  });
});
9.

Di dalam pemrograman frontend promises sering digunakan untuk permintaan jaringan. Jadi mari lihat contoh yang lebih luas dari itu.

Kita akan menggunakan methos fetch untuk memuat informasi tentang pengguna dari server jarak jauh. Banyak sekali pilihan parameter yang dilibatkan di dalam bab terpisah, tetapi sintaksis dasar cukup sederhana:

let promise = fetch(url);

Ini membuat permintaan jaringan ke

class Thenable {
  constructor(num) {
    this.num = num;
  }
  then(resolve, reject) {
    alert(resolve); // function() { native code }
    // selesai dengan this.num*2 setelah 1 detik
    setTimeout(() => resolve(this.num * 2), 1000); // (**)
  }
}

new Promise(resolve => resolve(1))
  .then(result => {
    return new Thenable(result); // (*)
  })
  .then(alert); // menunjukkan 2 setelah 1000ms
0 dan mengembalikkan sebuah promise. Promise selesai dengan objek
class Thenable {
  constructor(num) {
    this.num = num;
  }
  then(resolve, reject) {
    alert(resolve); // function() { native code }
    // selesai dengan this.num*2 setelah 1 detik
    setTimeout(() => resolve(this.num * 2), 1000); // (**)
  }
}

new Promise(resolve => resolve(1))
  .then(result => {
    return new Thenable(result); // (*)
  })
  .then(alert); // menunjukkan 2 setelah 1000ms
1 ketika server jarak jauh merespon dengan header, tetapi sebelum response penuh diunduh.

Untuk membaca response penuh, kita harus memanggil sebuah method

class Thenable {
  constructor(num) {
    this.num = num;
  }
  then(resolve, reject) {
    alert(resolve); // function() { native code }
    // selesai dengan this.num*2 setelah 1 detik
    setTimeout(() => resolve(this.num * 2), 1000); // (**)
  }
}

new Promise(resolve => resolve(1))
  .then(result => {
    return new Thenable(result); // (*)
  })
  .then(alert); // menunjukkan 2 setelah 1000ms
2: method tersebut mengembalikkan sebuah promise yang selesai ketika teks penuh ull telah diunduh dari server jarak jauh, dengan teks tersebut sebagai hasilnya.

Kode di bawah ini membuat permintaan ke

class Thenable {
  constructor(num) {
    this.num = num;
  }
  then(resolve, reject) {
    alert(resolve); // function() { native code }
    // selesai dengan this.num*2 setelah 1 detik
    setTimeout(() => resolve(this.num * 2), 1000); // (**)
  }
}

new Promise(resolve => resolve(1))
  .then(result => {
    return new Thenable(result); // (*)
  })
  .then(alert); // menunjukkan 2 setelah 1000ms
3 dan memuat teks dari server:

fetch("/article/promise-chaining/user.json")
  // .then di bawah berjalan ketika server jarak jauh merespon
  .then(function (response) {
    // response.text() mengembalikkan sebuah promise baru yang selesai dengan response teks penuh
    // ketika dimuat
    return response.text();
  })

  .then(function (text) {
    // ...dan di sini isi dari file remote
    alert(text); // {"name": "iliakan", isAdmin: true}
  });

Di sana juga ada method

class Thenable {
  constructor(num) {
    this.num = num;
  }
  then(resolve, reject) {
    alert(resolve); // function() { native code }
    // selesai dengan this.num*2 setelah 1 detik
    setTimeout(() => resolve(this.num * 2), 1000); // (**)
  }
}

new Promise(resolve => resolve(1))
  .then(result => {
    return new Thenable(result); // (*)
  })
  .then(alert); // menunjukkan 2 setelah 1000ms
4 yang membaca data remote dan parsing sebagai JSON. Pada kasus kita lebih sesuai, jadi mari ganti dengan itu.

.then(function(text) { // …and here’s the content of the remote file alert(text); // {“name”: “iliakan”, “isAdmin”: true} });

Kita juga akan menggunakan arrow functions untuk keringkasan:

```js run
// sama seperti di atas, tetapi response.json() parsing konten remote sebagai JSON
fetch("/article/promise-chaining/user.json")
  .then((response) => response.json())
  .then((user) => alert(user.name)); // iliakan, mendapatkan user name

Sekarang mari lakukan sesuatu dengan memuat pengguna.

Sebagai contoh, kita dapat membuat satu atau lebih permintaan ke GitHub, muat profil pengguna dan tunjukkan avatarnya:

let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
0

Kodenya bekerja, lihat komentar tentang detail. Meskipun, di sana ada potensi masalah di dalamnya, kesalahan umum dari mereka yang mulai menggunakan promise.

Lihat pada baris

let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
4: bagaimana kita dapat melakukan sesuatu setelah avatar telah muncul dan dihapus? sebagai contoh, kita ingin menunjukkan form untuk mengubah pengguna atau sesuatu yang lain. Sampai sekarang, tidak mungkin.

Untuk membuat chain bisa diperpanjang, kita butuh untuk mengembalikkan sebuah promise yang selesai ketika avatar selesai muncul.

Seperti ini:

let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
1

Itu adalah, handler

let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
3 pada baris
let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
4 sekarang mengembalikkan
class Thenable {
  constructor(num) {
    this.num = num;
  }
  then(resolve, reject) {
    alert(resolve); // function() { native code }
    // selesai dengan this.num*2 setelah 1 detik
    setTimeout(() => resolve(this.num * 2), 1000); // (**)
  }
}

new Promise(resolve => resolve(1))
  .then(result => {
    return new Thenable(result); // (*)
  })
  .then(alert); // menunjukkan 2 setelah 1000ms
8, yang menjadi mengendap hanya setelah pemanggilan
class Thenable {
  constructor(num) {
    this.num = num;
  }
  then(resolve, reject) {
    alert(resolve); // function() { native code }
    // selesai dengan this.num*2 setelah 1 detik
    setTimeout(() => resolve(this.num * 2), 1000); // (**)
  }
}

new Promise(resolve => resolve(1))
  .then(result => {
    return new Thenable(result); // (*)
  })
  .then(alert); // menunjukkan 2 setelah 1000ms
9 dalam
let promise = fetch(url);
0
let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
6.

let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
3 selanjutnya di dalam chain akan menunggu untuk itu.

Seperti peraturan yang bagus, sebuah aksi asynchronous harus selalu mengembalikkan sebuah promise.

Itu membuat kemungkinan untuk rencana aksi setelahnya. Bahkan jika kita tidak berencana memperpanjang chain sekarang, kita mungkin membutuhkannya nanti.

Akhinya, kita dapat memecah kodenya ke dalam function yang dapat digunakan kembali:

let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
2

Jika ada handler

let promise = new Promise(function (resolve, reject) {
  setTimeout(() => resolve(1), 1000);
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});

promise.then(function (result) {
  alert(result); // 1
  return result * 2;
});
3 (atau
let promise = fetch(url);
4, tidak masalah) mengembalikkan sebuah promise, chain sisanya akan menunggu sampai mengendap. Saat itu terjadi, hasilnya (atau error) diteruskan lebih jauh.

Javascript Apa Itu Promise?

Promise merupakan salah satu fitur yang penting dari ES6. Objek promise mewakili penyelesaian atau sebuah kesalahan pada operasi Asynchronous. Pada artikel sebelumnya kita telah belajar tentang Asynchnous pada javascript, tak lengkap rasanya apabila kita belum paham tentang Promise.

Kapan kita menggunakan asynchronous?

Proses asynchronous sering digunakan untuk komunikasi data, karena data menjadi bagian inti dari sebuah aplikasi maka konsep asynchronous sangat penting untuk dipahami.

Apa itu async Await Javascript?

Async/await adalah fitur yang hadir sejak ES2017. Fitur ini mempermudah kita dalam menangani proses asynchronous.Async/Await merupakan sebuah syntax khusus yang digunakan untuk menangani Promise agar penulisan code lebih efisien dan rapih.