ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScript での非同期プログラミングの初心者ガイド
JavaScript のシングルスレッド
単一スレッドがプログラムを実行する場合、取得されるプログラム パスは連続した順序で配置され、後のパスが実行される前に、前のパスが処理される必要があります。特定の時間に特定のコードのみを実行でき、他のコードはブロックされます。
シングルスレッドは、ひたむきで献身的な、夢中になっている少年です。シングルスレッドとは、プロセスにスレッドが 1 つだけあることを意味し、マルチスレッドとは、プロセスに複数のスレッドがあることを意味します。
JavaScript のシングルスレッド言語実行環境とその欠点に基づいて、JavaScript の同期および非同期プログラミング手法が提案されています。
同期とは、タスクが段階的に実行され、現在のコードが実行された後でのみ後続のコードを実行できることを意味します。非同期とは、現在のコードと後続のコードの実行を開始した後に待つ必要がないことを意味します。現在のタスクの実行が完了した後、タスクを続行することができ、ステータスと通知を呼び出し元に通知することができます。
JavaScriptでの非同期プログラミング
JavaScript 言語の実行環境はシングルスレッドです。シングルスレッドでプログラムを実行する場合、最初のプログラム パスは、後のパスが実行される前に処理される必要があります。特定の時間に特定のコードのみを実行でき、他のコードはブロックされます。この記事では、JavaScript 非同期プログラミングについて説明します。
JavaScript 非同期プログラミングの実装
JavaScript 非同期プログラミングの実装は、主にコールバック関数、パブリッシュとサブスクライブ、Promise オブジェクトの 3 つのカテゴリに分類されます。
コールバック関数
function a(fn) { //a函数任务... setTimeout(function() { fn(); }, 0); console.log('a'); } function b(fn) { //b函数任务 console.log('b'); } a(b); 以上代码打印值顺序如何呢?结果是先a后b。至于为什么,不得不说说setTimeout。再细微的东西,只要存在,我们都能从中弄出些精华,就比如setTimeout。 请看代码: ··· for (var i = 0; i < 5; i ++) { setTimeout(function(){ console.log(i); }, 0); } console.log(i); //5 ; 5 ; 5 ; 5; 5 ···
all は 5 を出力します。理由を理解するには、次の 3 つの点を理解する必要があります:
i ここで、for ループが配置されているコンテキスト環境の変数であり、i は 1 つだけです。
i== ループ終了時 5;JavaScript シングルスレッド イベント ハンドラーは、スレッドがアイドル状態になるまで次のイベントを実行しません。 次のようなコードを見たことがあるかもしれません:·
·· function f1(callback) { setTimeout(function() { f2(functions() { setTimeout({ callback(...) ; }, 0); }); }, 0); } function(callback) {//...} ···
请避免这样的多层嵌套回调。
发布订阅
PubSub,即Publish/Subscribe,发布、订阅模式, 用以分发事件。常见的有jQuery的自定义事件监听、Node的EventEmitter对象等。
jQuery事件监听
$('#btn').on('myEvent', function(e) { console.log('There is my Event'); }); $('#btn').trigger('myEvent'); PubSub var PubSub = function(){ this.handlers = {}; }; PubSub.prototype.subscribe = function(eventType, handler) { if (!(eventType in this.handlers)) { this.handlers[eventType] = []; } this.handlers[eventType].push(handler); //添加事件监听器 return this;//返回上下文环境以实现链式调用 }; PubSub.prototype.publish = function(eventType) { var _args = Array.prototype.slice.call(arguments, 1); for (var i = 0, _handlers = this.handlers[eventType]; i < _handlers.length; i++) { _handlers[i].apply(this, _args);//遍历事件监听器 } return this; }; var event = new PubSub;//构造PubSub实例 event.subscribe('list', function(msg) { console.log(msg); }); event.publish('list', {data: ['one,', 'two']}); //Object {data: Array[2]}
以上代码就是一个简易的订阅发布模式基本实现,还可以对其进行完善,如添加只执行一次事件监听器等。
Promise对象
Promise是CommonJS的规范之一,拥有resolve、reject、done、fail、then等方法,能够帮助我们控制代码的流程。
一个promise可能有三种状态:等待(pending)、已完成(fulfilled)、已拒绝(rejected);
一个promise的状态只可能从“等待”转到“完成”态或者“拒绝”态,不能逆向转换,同时“完成”态和“拒绝”态不能相互转换;
promise必须实现then方法(可以说,then就是promise的核心),而且then必须返回一个promise,同一个promise的then可以调用多次,并且回调的执行顺序跟它们被定义时的顺序一致;
then方法接受两个参数,第一个参数是成功时的回调,在promise由“等待”态转换到“完成”态时调用,另一个是失败时的回调,在promise由“等待”态转换到“拒绝”态时调用。
同时,then可以接受另一个promise传入,也接受一个“类then”的对象或方法,即thenable对象。
* jQuery之Promise var prom = new $.Deferred(); prom.done(function(value) { console.log(value + ' Done'); }); prom.fail(function(value) { console.log(value + ' Fail'); }); prom.always(function(v) { console.log(' always here'); }); prom.resolve('OK'); Deferred是Promise的超集,相对于Promise只提供then方法添加调用,触发这些调用需要其他支持,使用Deferred实例可直接触发调用。 Promise简单实现 function defer() { var tasks = [], progresses = [], state = 'pending', value, reason; return { resolve: function(_value) { if (tasks) { value = ref(_value); tasks.forEach(function(task) { nextTick(function() { value.then.apply(value, task); }); }); tasks = null; state = 'resolved'; }else { if (state === 'resolved') { throw new Error('A promise should been resolved once.'); } } }, reject: function(reason) { if (tasks) { value = ref(reason); tasks.forEach(function(task) { nextTick(function() { value.then.apply(value, [task[1], task[0]]); }); }); tasks = undefined; state = 'rejected'; }else { if (state === 'rejected') { throw new Error('A promise should been rejected once.'); } } }, notify: function(progress) { if (state === 'resolved' || state === 'rejected') { return; } progresses.push(progress); }, promise: { then: function(_callback, _errback, _notifyback) { var deferred = defer(); _callback = _callback || function(value) { return value; }; _errback = _errback || function(reason) { return reject(reason); }; _notifyback = _notifyback || function(progress) { return progress; }; var callback = function(value) { var result; try { result = _callback(value); }catch(e) { deferred.reject(e); }finally { deferred.resolve(result); } }; var errback = function(reason) { var result; try { result = _errback(reason); }catch(e) { deferred.reject(e); }finally { deferred.resolve(result); } } nextTick(function() { while (progresses.length) { try { _notifyback(progresses.shift()); }catch(e) { deferred.reject(e); break; } } }); if (tasks) { tasks.push([callback, errback]); }else { nextTick(function() { if (state === 'rejected') { value.then(errback); }else if (state === 'resolved') { value.then(callback); } }); } return deferred.promise; } } }; } var ref = function(value) { if (value && typeof value.then === 'function') { return value; } return { then: function(callback) { return ref(callback(value)); } } }; var reject = function(reason) { return { then: function(callback, errback) { return ref(errback(reason)); } }; }; var nextTick = function(callback) { setTimeout(callback, 0); }; //Promise实例 var deferred = defer(), promise = deferred.promise; promise.then(function(value) { console.log(value); throw 'zhangsan'; }).then(function (v) { console.log(v); }, function (err) { console.error(err); done(); }); setTimeout(function () { deferred.resolve('zhangsan1'); }, 1000);
以上就是js异步编程入门的全部内容了,感谢大家的阅读!
以上がJavaScript での非同期プログラミングの初心者ガイドの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。