Ini bukan masalah dunia nyata, saya hanya mencoba memahami bagaimana janji dibuat.
Saya perlu memahami cara membuat janji untuk fungsi yang tidak mengembalikan apa-apa, seperti setTimeout.
Misalkan saya memiliki:
function async(callback){
setTimeout(function(){
callback();
}, 5000);
}
async(function(){
console.log('async called back');
});
Bagaimana cara membuat janji yang async
dapat dikembalikan setelah setTimeout
siap callback()
?
Saya kira membungkusnya akan membawa saya ke suatu tempat:
function setTimeoutReturnPromise(){
function promise(){}
promise.prototype.then = function() {
console.log('timed out');
};
setTimeout(function(){
return ???
},2000);
return promise;
}
Tapi saya tidak bisa berpikir lebih jauh dari ini.
javascript
settimeout
promise
refleks tertinggal
sumber
sumber
async function async(){...}
Jawaban:
Pembaruan (2017)
Di sini, di tahun 2017, Promises dibuat ke dalam JavaScript, dan ditambahkan oleh spesifikasi ES2015 (polyfill tersedia untuk lingkungan lama seperti IE8-IE11). Sintaks yang mereka gunakan menggunakan callback yang Anda berikan ke
Promise
konstruktor (Promise
pelaksana ) yang menerima fungsi untuk menyelesaikan / menolak janji sebagai argumen.Pertama, karena
async
sekarang memiliki arti dalam JavaScript (meskipun itu hanya kata kunci dalam konteks tertentu), saya akan menggunakanlater
nama fungsinya untuk menghindari kebingungan.Penundaan Dasar
Menggunakan janji asli (atau polyfill yang setia) akan terlihat seperti ini:
function later(delay) { return new Promise(function(resolve) { setTimeout(resolve, delay); }); }
Perhatikan bahwa itu mengasumsikan versi
setTimeout
yang sesuai dengan definisi untuk browser di manasetTimeout
tidak meneruskan argumen apa pun ke callback kecuali Anda memberikannya setelah interval (ini mungkin tidak benar di lingkungan non-browser, dan tidak dulu benar di Firefox, tetapi sekarang; itu benar di Chrome dan bahkan di IE8).Penundaan Dasar dengan Nilai
Jika Anda ingin fungsi Anda meneruskan nilai resolusi secara opsional, pada browser modern apa pun yang memungkinkan Anda memberikan argumen tambahan
setTimeout
setelah penundaan dan kemudian meneruskannya ke callback saat dipanggil, Anda dapat melakukan ini (Firefox dan Chrome saat ini; IE11 + , mungkin Edge; bukan IE8 atau IE9, tidak tahu tentang IE10):function later(delay, value) { return new Promise(function(resolve) { setTimeout(resolve, delay, value); // Note the order, `delay` before `value` /* Or for outdated browsers that don't support doing that: setTimeout(function() { resolve(value); }, delay); Or alternately: setTimeout(resolve.bind(null, value), delay); */ }); }
Jika Anda menggunakan fungsi panah ES2015 +, itu bisa lebih ringkas:
function later(delay, value) { return new Promise(resolve => setTimeout(resolve, delay, value)); }
atau bahkan
const later = (delay, value) => new Promise(resolve => setTimeout(resolve, delay, value));
Penundaan yang Dapat Dibatalkan dengan Nilai
Jika Anda ingin memungkinkan untuk membatalkan waktu tunggu, Anda tidak bisa hanya mengembalikan janji dari
later
, karena janji tidak bisa dibatalkan.Tapi kita bisa dengan mudah mengembalikan objek dengan
cancel
metode dan aksesor untuk promise, dan menolak promise saat pembatalan:const later = (delay, value) => { let timer = 0; let reject = null; const promise = new Promise((resolve, _reject) => { reject = _reject; timer = setTimeout(resolve, delay, value); }); return { get promise() { return promise; }, cancel() { if (timer) { clearTimeout(timer); timer = 0; reject(); reject = null; } } }; };
Contoh Langsung:
const later = (delay, value) => { let timer = 0; let reject = null; const promise = new Promise((resolve, _reject) => { reject = _reject; timer = setTimeout(resolve, delay, value); }); return { get promise() { return promise; }, cancel() { if (timer) { clearTimeout(timer); timer = 0; reject(); reject = null; } } }; }; const l1 = later(100, "l1"); l1.promise .then(msg => { console.log(msg); }) .catch(() => { console.log("l1 cancelled"); }); const l2 = later(200, "l2"); l2.promise .then(msg => { console.log(msg); }) .catch(() => { console.log("l2 cancelled"); }); setTimeout(() => { l2.cancel(); }, 150);
Jawaban Asli dari 2014
Biasanya Anda akan memiliki perpustakaan promise (yang Anda tulis sendiri, atau salah satu dari beberapa di luar sana). Perpustakaan itu biasanya akan memiliki objek yang bisa Anda buat dan kemudian "diselesaikan", dan objek itu akan memiliki "janji" yang bisa Anda dapatkan darinya.
Maka
later
akan cenderung terlihat seperti ini:function later() { var p = new PromiseThingy(); setTimeout(function() { p.resolve(); }, 2000); return p.promise(); // Note we're not returning `p` directly }
Dalam komentar atas pertanyaan itu, saya bertanya:
dan kamu berkata
Untuk membantu pemahaman itu, berikut adalah contoh yang sangat mendasar , yang tidak sesuai dengan Promises-A dari jarak jauh: Live Copy
<!DOCTYPE html> <html> <head> <meta charset=utf-8 /> <title>Very basic promises</title> </head> <body> <script> (function() { // ==== Very basic promise implementation, not remotely Promises-A compliant, just a very basic example var PromiseThingy = (function() { // Internal - trigger a callback function triggerCallback(callback, promise) { try { callback(promise.resolvedValue); } catch (e) { } } // The internal promise constructor, we don't share this function Promise() { this.callbacks = []; } // Register a 'then' callback Promise.prototype.then = function(callback) { var thispromise = this; if (!this.resolved) { // Not resolved yet, remember the callback this.callbacks.push(callback); } else { // Resolved; trigger callback right away, but always async setTimeout(function() { triggerCallback(callback, thispromise); }, 0); } return this; }; // Our public constructor for PromiseThingys function PromiseThingy() { this.p = new Promise(); } // Resolve our underlying promise PromiseThingy.prototype.resolve = function(value) { var n; if (!this.p.resolved) { this.p.resolved = true; this.p.resolvedValue = value; for (n = 0; n < this.p.callbacks.length; ++n) { triggerCallback(this.p.callbacks[n], this.p); } } }; // Get our underlying promise PromiseThingy.prototype.promise = function() { return this.p; }; // Export public return PromiseThingy; })(); // ==== Using it function later() { var p = new PromiseThingy(); setTimeout(function() { p.resolve(); }, 2000); return p.promise(); // Note we're not returning `p` directly } display("Start " + Date.now()); later().then(function() { display("Done1 " + Date.now()); }).then(function() { display("Done2 " + Date.now()); }); function display(msg) { var p = document.createElement('p'); p.innerHTML = String(msg); document.body.appendChild(p); } })(); </script> </body> </html>
sumber
const setTimeoutAsync = (cb, delay) => new Promise((resolve) => { setTimeout(() => { resolve(cb()); }, delay); });
Kita bisa lewat custom 'cb fxn' seperti ini 👆🏽
sumber
Ini bukanlah jawaban dari pertanyaan awal. Tapi, karena pertanyaan orisinal bukanlah masalah dunia nyata, ini seharusnya tidak menjadi masalah. Saya mencoba menjelaskan kepada teman apa saja yang menjadi promise dalam JavaScript dan perbedaan antara promise dan callback.
Kode di bawah ini berfungsi sebagai penjelasan:
//very basic callback example using setTimeout //function a is asynchronous function //function b used as a callback function a (callback){ setTimeout (function(){ console.log ('using callback:'); let mockResponseData = '{"data": "something for callback"}'; if (callback){ callback (mockResponseData); } }, 2000); } function b (dataJson) { let dataObject = JSON.parse (dataJson); console.log (dataObject.data); } a (b); //rewriting above code using Promise //function c is asynchronous function function c () { return new Promise(function (resolve, reject) { setTimeout (function(){ console.log ('using promise:'); let mockResponseData = '{"data": "something for promise"}'; resolve(mockResponseData); }, 2000); }); } c().then (b);
JsFiddle
sumber