이 글은 주로 Node 비동기 프로그래밍의 메커니즘을 소개합니다. 편집자는 이것이 꽤 좋다고 생각합니다. 이제 여러분과 공유하고 참고하겠습니다. 편집자를 따라 살펴보겠습니다. 모두에게 도움이 되기를 바랍니다.
이 문서에서는 노드 비동기 프로그래밍을 소개하고 모든 사람과 공유합니다. 세부 사항은 다음과 같습니다.
현재 비동기 프로그래밍의 주요 솔루션은 다음과 같습니다.
이벤트 게시/구독 모드
Promise/Deferred 모드
프로세스 제어 라이브러리
이벤트 게시/구독 모드
노드 자체가 이벤트 모듈을 제공하여 이벤트 게시/구독을 쉽게 구현할 수 있습니다.
//订阅 emmiter.on("event1",function(message){ console.log(message); }) //发布 emmiter.emit("event1","I am mesaage!");
리스너를 유연하게 추가하고 삭제할 수 있습니다. 이벤트와 특정 처리 로직을 쉽게 연결하고 분리할 수 있습니다.
이벤트 게시/구독 모델은 비즈니스 로직을 분리하는 데 종종 사용됩니다. 이벤트 게시자는 구독하는 리스너가 비즈니스 로직을 구현하는 방법이나 심지어 리스너 수에 주의를 기울일 필요가 없습니다. 리스너가 존재하며, 메시지를 통해 유연하게 데이터를 전송할 수 있습니다.
다음 HTTP는 일반적인 애플리케이션 시나리오입니다
var req = http.request(options,function(res){ res.on('data',function(chunk){ console.log('Body:'+ chunk); }) res.on('end',function(){ //TODO }) })
이벤트에 리스너가 10명 이상 추가되면 emmite.setMaxListeners(0)
을 호출하여 이 제한을 제거할 수 있습니다. 이벤트 모듈 상속
var events = require('events'); function Stream(){ events.EventEmiiter.call(this); } util.inherits(Stream,events.EventEmitter);
이벤트 큐를 사용하여 눈사태 문제 해결
소위 눈사태 문제는 높은 액세스 볼륨과 대규모 동시성 조건에서 캐시 오류가 발생하는 것입니다. 동시에 수많은 요청이 데이터베이스에 통합되면 데이터베이스는 동시에 이러한 대규모 쿼리 요청을 견딜 수 없으므로 웹사이트의 전체 응답 속도에 더욱 영향을 미칩니다. 다중 비동기 이벤트 사이의 솔루션var proxy = new events.EventEmitter(); var status = "ready"; var seletc = function(callback){ proxy.once("selected",callback);//为每次请求订阅这个查询时间,推入事件回调函数队列 if(status === 'ready'){ status = 'pending';//设置状态为进行中以防止引起多次查询操作 db.select("SQL",function(results){ proxy.emit("selected",results); //查询操作完成后发布时间 status = 'ready';//重新定义为已准备状态 }) } }부분 함수 체계
var count = 0 ; var results = {}; var done = function(key,value){ result[key] = value; count++; if(count === 3){ render(results); } } fs.readFile(template_path,"utf8",function(err,template){ done('template',template) }) db.query(sql,function(err,data){ done('data',data); }) l10n.get(function(err,resources){ done('resources',resources) })
EventProxy 모듈 체계 소개
var after = function(times,callback){ var count = 0, result = {}; return function(key,value){ results[key] = value; count++; if(count === times){ callback(results); } } } var done = after(times,render); var emitter = new events.Emitter(); emitter.on('done',done); //一个侦听器 emitter.on('done',other); //如果业务增长,可以完成多对多的方案 fs.readFile(template_path,"utf8",function(err,template){ emitter.emit('done','template',template); }) db.query(sql,function(err,data){ emitter.emit('done','data',data); }) l10n.get(function(err,resources){ emitter.emit('done','resources',resources) })
Promise/Deferred 모드
위 방식으로 이벤트를 사용할 경우 실행 프로세스를 미리 설정해야 하며 이는 게시/구독 모드의 작동 메커니즘에 따라 결정됩니다.
var proxy = new EventProxy(); proxy.all('template','data','resources',function(template,data,resources){ //TODO }) fs.readFile(template_path,'utf8',function(err,template){ proxy.emit('template',template); }) db.query(sql,function(err,data){ proxy.emit('data',data); }) l10n.get(function(err,resources){ proxy.emit('resources',resources); })
Promise/A
Promise/A는 단일 비동기 작업에 대해 다음과 같은 추상 정의를 제안합니다.
Promise 상태는 완료되지 않음에서 완료 또는 실패로만 변환되며, 완료됨 상태와 실패한 상태는 서로 변환될 수 없습니다.
Promise 상태가 변환되면 변경할 수 없습니다.$.get('/api',{ success:onSuccess, err:onError, complete:onComplete }) //需要严谨设置目标
var Promise = function(){ EventEmitter.call(this) } util.inherits(Promise,EventEmitter); Promise.prototype.then = function(fulfilledHandler,errHandler,progeressHandler){ if(typeof fulfilledHandler === 'function'){ this.once('success',fulfilledHandler); //实现监听对应事件 } if(typeof errorHandler === 'function'){ this.once('error',errorHandler) } if(typeof progressHandler === 'function'){ this.on('progress',progressHandler); } return this; }따라서 일반적인 응답 객체는
var Deferred = function(){ this.state = 'unfulfilled'; this.promise = new Promise(); } Deferred.prototype.resolve = function(obj){ //当异步完成后可将resolve作为回调函数,触发相关事件 this.state = 'fulfilled'; this.promise.emit('success',obj); } Deferred.prototype.reject = function(err){ this.state = 'failed'; this.promise.emit('error',err); } Deferred.prototype.progress = function(data){ this.promise.emit('progress',data) }로 캡슐화하여
res.setEncoding('utf8'); res.on('data',function(chunk){ console.log("Body:" + chunk); }) res.on('end',function(){ //done }) res.on('error',function(err){ //error }로 변환할 수 있습니다. 위 변환을 완료하려면 먼저 res 객체, data, end, Error를 캡슐화해야 합니다. 및 기타 이벤트는 promisify
res.then(function(){ //done },function(err){ //error },function(chunk){ console.log('Body:' + chunk); })위는 Deferred에 비즈니스의 불변 부분을 캡슐화하고 변수 부분을 Promise에 넘겨줍니다.
Promise의 다중 비동기 협업
var promisify = function(res){ var deferred = new Deferred(); //创建一个延迟对象来在res的异步完成回调中发布相关事件 var result = ''; //用来在progress中持续接收数据 res.on('data',function(chunk){ //res的异步操作,回调中发布事件 result += chunk; deferred.progress(chunk); }) res.on('end',function(){ deferred.resolve(result); }) res.on('error',function(err){ deferred.reject(err); }); return deferred.promise //返回deferred.promise,让外界不能改变deferred的状态,只能让promise的then()方法去接收外界来侦听相关事件。 } promisify(res).then(function(){ //done },function(err){ //error },function(chunk){ console.log('Body:' + chunk); })
코드를 변환하여 체인 호출을 구현해 보세요
Deferred.prototype.all = function(promises){ var count = promises.length; //记录传进的promise的个数 var that = this; //保存调用all的对象 var results = [];//存放所有promise完成的结果 promises.forEach(function(promise,i){//对promises逐个进行调用 promise.then(function(data){//每个promise成功之后,存放结果到result中,count--,直到所有promise被处理完了,才出发deferred的resolve方法,发布事件,传递结果出去 count--; result[i] = data; if(count === 0){ that.resolve(results); } },function(err){ that.reject(err); }); }); return this.promise; //返回promise来让外界侦听这个deferred发布的事件。 } var promise1 = readFile('foo.txt','utf-8');//这里的文件读取已经经过promise化 var promise2 = readFile('bar.txt','utf-8'); var deferred = new Deferred(); deferred.all([promise1,promise2]).thne(function(results){//promise1和promise2的then方法在deferred内部的all方法所调用,用于同步所有的promise //TODO },function(err){ //TODO })
Javascript의 비동기 프로그래밍 4가지 방법 소개
비동기 프로그래밍 설명 es6의 Promise상세 자바스크립트 비동기 프로그래밍의 콜백 함수 및 관리자 사용 예에 대한 설명
위 내용은 노드 비동기 프로그래밍 메커니즘에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!