Javascript NonBlocking I/O




Javascript Non-Blocking I/O




I/O란?


terms:

http://terms.co.kr/IO.htm


wiki:

http://ko.wikipedia.org/wiki/%EC%9E%85%EC%B6%9C%EB%A0%A5





Blocking I/O(동기 I/O): 요청한 I/O(DB, 파일, 네트웍 등..)가 완료될때까지 해당 Thread(Single, Multi)를 "대기 모드"로 돌렸다가 I/O 완료 후 유저 코드를 실행시킨다.



var ret1 = $.post('http://mohwa.org/html/defaultTest.html?type=DB');
	
// I/O가 완료된 후 대기중이었던 유저 코드(새로운 요청)가 실행된다.
var ret2 = $.post('http://mohwa.org/html/defaultTest.html?type=File');




NonBlocking I/O(비동기 I/O): 요청한 I/O의 완료 여부와 관계없이 바로 리턴해서 유저 코드가 계속 실행되도록 한다. 이때 유저 코드는 요청한 I/O가 완료(HTTP 응답 등과 같은...)될때까지 다른 사용자의 요청을 처리할 수 있다.



var ret1 = $.post('http://mohwa.org/html/defaultTest.html?type=DB', function(ret){
	// callback
	console.log('NonBlocking I/O callback pattern' + new Date().getTime());
});

// I/O 완료와 관계없이 바로 리턴되며, 유저 코드(새로운 요청)가 계속해서 실핸된다.
var ret2 = $.post('http://mohwa.org/html/defaultTest.html?type=File', function(ret){
	// callback
	console.log('NonBlocking I/O callback pattern' + new Date().getTime());
});



보통 "Single Thread" 방식 언어의 비동기 구현을 위해 Non-Blocking I/O 방식이 사용된다.(Node.js API 또한 이 방식으로 구현 되었다.)


하지만 이 방식을 사용(채택, 구현)하기 위해서는 기존 OS단에서 자동으로 처리되던 Thread 스위칭 작업일정 부분 유저 코드로 구현(비동기 처리)해야 한다는 부담이 존재한다.




* AJAX(XmlHttpRequest) API Node.js APINon-Blocking I/O 방식으로 구현되어 있다.






Non-Blocking I/O(비동기) 방식 도식화 이미지:







JQuery Ajax 관련 코드(Non-Blocking I/O 방식과 Callback Pattern 사용)


$.post('http://mohwa.org/html/defaultTest.html', function(ret){
console.log('NonBlocking I/O callback pattern' + new Date().getTime());
});




Non-Blocking I/O 방식이란?

http://drypot.tumblr.com/post/11175657085/node



Javascript Single Thead or Asynchronous





Javascript Single Thead or Asynchronous




1. JS 언어는 Single Thread 방식이며, 모든 비동기 이벤트(Event Callback,  타이머(setTimeout, setInterval)는 같은 Thread 위에서 실행된다.



2. JS 언어는 Event Loop 방식이며, 비동기 이벤트를 사용한다.(여기서 Event Loop라는 것은 동작을 요청 후 "CallBack"을 지정하여 동작이 완료되면 콜백이 실행되는 방식을 말한다.(비동기 동작 방식))






3. 모든 비동기 이벤트는 완료 시점의 순서를 보장하지 않는다.


즉, "실행"은 순서를 보장하지만, 그에 따른 완료(callback) 시점은 보장하지 않는다.(어떤 것이 먼저 종료될지 전혀 알 수 없다.)


4. 비동기 이벤트가 "실행" 되는 시점호출되는 시점이 아닌 호출되는 코드가 포함된 Javascript Code Block이 완료된 시점이다.



관련 예제 코드:


(function(){
	console.log('for start time:' + new Date().getSeconds());
	
	for (var i = 0; i < 100000; i++){
		console.log();
	}
	
	console.log('for end time:' + new Date().getSeconds());
	
	// 비동기 이벤트인 serTimeout 실행 시점은 위 순회문 종료 후 3초뒤 실행된다.
	this.setTimeout(function(){
		console.log('setTimeout start time:' + new Date().getSeconds());
	}, 3000)
})();


위 코드 중 비동기 이벤트인 setTimeout(큐에 저장된)의 실행 시점은 해당 Javascript Code Block 안의 for(순회)문 종료 후 3초뒤 실행된다.



4. setInterval 실행 코드가 이미 큐에 이미 들어가있다면, 그 다음 간격(Interval Time)으로 실행되어야 할 코드는 에 쌓이지 않고 Drop된다.(즉, 최초 Interval Timer만 큐에 쌓인다.)



5. 브라우저에 따라 차이가 존재하지만 Timer에 전달하는 최소 시간은 10ms ~ 15ms로 지정하는것이 좋다.(하위 호환성을 위해)











- 위 그림은 JS의 비동기 이벤트 실행 순서를 나타내고 있다.(Javascript Code Block --> Click Event --> Timer)





구현 코드 블럭:








- "테스트 결과" 비동기 이벤트 실행 및 완료 시점은 아래와 같습니다.



 실행: javascript code block --> onload code block --> setTimeout code block --> setTimeout code block --> setInterval code block --> setInterval code block



완료: javascript code block --> onclick code block --> setTimeout code block(무작위) --> setTimeout code block(무작위) --> setInterval code block(무작위) --> setInterval code block(무작위)





동기 / 비동기

http://kineo2k.tistory.com/29


Javascript 비동기 프로그래밍:

http://blog.naver.com/PostList.nhn?from=postList&blogId=bitofsky&categoryNo=54&currentPage=1


Javascript Timer:

http://okjungsoo.tistory.com/7954014


How Javascript Timer Work:

http://webmeme.tistory.com/entry/How-Javascript-Timer-Work




[CookBook] 자바스크립트 객체



1. 자바스크립트 객체 정의하기


함수 생성자와 new 연산자를 활용해 새로운 인스턴스를 생성한다. 또한, 인스턴스 생성 시 함수 내부로 전달되는 this(scope)에 대해 알아본다.



function User(/*string*/uid, /*string*/uname) {
    
    // this 객체 User 생성자(class)의 인스턴스가 아니라면...
    if (!(this instanceof User)) return null;

    this.uid = uid;
    this.uname = uname;

    this.constructor = this.constructor;
    return this;
}

// this.constructor === User
console.debug(new User('mohwa', 'mohwaName').uid);
console.debug(new User('mohwa', 'mohwaName').uname);
console.debug(new User('mohwa', 'mohwaName').constructor);


try
{
    // this.constructor === Window
    User('mohwa', 'mohwaName');
    console.debug(window['uid']);
    console.debug(window['uname']);
}
catch(e){
    console.debug('error=' + e.message);
}


1. 자바스크립트에서 함수는 객체이다.

http://mohwaproject.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%8A%A4%EC%BD%94%ED%94%84


2. Javascript new 단항 연산자의 객체 인스턴스 생성 프로세스

http://mohwaproject.tistory.com/entry/javascript-new-%EC%97%B0%EC%82%B0%EC%9E%90%EC%9D%98-%EA%B0%9D%EC%B2%B4-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-%EC%83%9D%EC%84%B1-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4





2. 객체 맴버를 비공개로 만들기


"특권 메서드(Closure 활용)"란? 비공개 맴버(private)에 접근 가능하며, 그 자신은 public 인 메서드(getter(), setter()와 동일)



function User(/*string*/uid, /*string*/name) {

    // this 객체 User 생성자(class)의 인스턴스가 아니라면...
    if (!(this instanceof User)) return null;

    this.uid = uid;

    var name = name;

    // 특권 메서드
    this.getName = function () {
        return name;
    }

    this.constructor = this.constructor;

    return this;
}

console.debug(new User('mohwa', 'mohwaName').uid);
console.debug(new User('mohwa', 'mohwaName').name);
console.debug(new User('mohwa', 'mohwaName').getName());

javascript private member 
http://mohwaproject.tistory.com/entry/javascript-private-member






3. 프로토타입(객체)으로 객체 확장하기


"프로토타입" 상속을 통해 어떤 객체(내장, 생성된)든 확장 가능하다.


또한, 프로그램 안에서 재사용될 메서드(보통 프로토 타입 맴버에 할당한다. 이유는 생성자 내부의 인스턴스 맴버와 다르게 생성 시 한번만 실행되기 때문이다.)와 같은 경우 효율을 위해 인스턴스 맴버가 아닌 프로토타입 맴버에 추가시킨다.



function User1(/*string*/uid, /*string*/name) {

    // this 객체 User 생성자(class)의 인스턴스가 아니라면...
    if (!(this instanceof User1)) return null;

    // 인스턴스 맴버
    this.uid = uid;
    this.name = name;

    this.constructor = this.constructor;

    console.log('Instance members=' + this.uid);

    return this;
}

// 프로토타입 맴버(재 사용 메서드 추가)
User1.prototype.getId = function () {
    console.log('Prototype members=' + this.uid);
    return this.uid;
}

var mohwa1 = new User1('mohwa1', 'mohwaName1');
var mohwa2 = new User1('mohwa2', 'mohwaName2');
var mohwa3 = new User1('mohwa3', 'mohwaName3');

// 한번만 실행된다.
mohwa3.getId();

String.prototype.trim = function () {
    return this.replace(/^\s+|\s+$/g, '');
}

console.log('    mohwa    '.trim());


자바스크립트 프로토타입 체인

http://mohwaproject.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-prototype-%EC%B2%B4%EC%9D%B8


자바스크립트 상속(클래스 방식 상속)

http://mohwaproject.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%83%81%EC%86%8D-5






4. 객체 기능 상속하기



자바스크립트 기본 상속


function User3(/*string*/uid, /*string*/name) {

    // this 객체 User 생성자(class)의 인스턴스가 아니라면...
    if (!(this instanceof User3)) return null;

    // 인스턴스 맴버
    this.uid = uid;
    this.name = name;

    return this;
}

// 프로토타입 맴버
User3.prototype.getId = function () {
    return this.uid;
}

// 프로토타입 객체에 new User3() 객체연결(가장 기본적인 상속 구조)
function clon1(target) {

    target = target || function () { ; };

    var f = function () {
        return this;
    };

    var slice = Array.prototype.slice;
    // 객체 상속
    f.prototype = new target(slice.call(arguments, 1)[0], slice.call(arguments, 1)[1]);

    return new f();
}

var clonObject1 = clon1(User3, 'mohwa1', 'mohwaName1');
console.log(clonObject1.uid);
console.log(clonObject1.name);
console.log(clonObject1.getId);


자바스크립트 상속 1

http: //mohwaproject.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%83%81%EC%86%8D-1

        

자바스크립트 상속 2

http://mohwaproject.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%83%81%EC%86%8D-2




함수 인스턴스 맴버 빌려쓰기(상속)


function User3(/*string*/uid, /*string*/name) {

    // this 객체 User 생성자(class)의 인스턴스가 아니라면...
    if (!(this instanceof User3) && !(this instanceof clon2)) return null;

    // 인스턴스 맴버
    this.uid = uid;
    this.name = name;

    return this;
}

// 함수 인스턴스 맴버 빌려쓰기(상속)
function clon2(target) {

    if (!(this instanceof clon2)) return null;
                
    target = target || function () { ; };

    // 인스턴스 맴버 복사
    target.apply(this, Array.prototype.slice.call(arguments, 1));

    return this;
}

var clonObject2 = new clon2(User3, 'mohwa1', 'mohwaName1');
console.log(clonObject2.uid);
console.log(clonObject2.name);
// 인스턴스 맴버만 복사되었기 때문에 프로토타입 맴버인 getId() 메서드는 사용할 수 없다.
console.log(clonObject2.getId);


자바스크립트 상속 3 http://mohwaproject.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%83%81%EC%86%8D-3 

자바스크립트 상속 4 http://mohwaproject.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%83%81%EC%86%8D-4





함수(원형) 복사 및 함수 프로토타입 맴버 복사.

프로토타입 맴버(객체)에 객체를 연결하는 방법이 아닌 다른 방법으로 해당 함수가 가진 모든 맴버(인스턴스, 프로토타입)를 복사하는 방법(하지만 억지스러운 면이 없지 않다.)



function User3(/*string*/uid, /*string*/name) {

    // this 객체 User 생성자(class)의 인스턴스가 아니라면...
    if (!(this instanceof User3)) return null;

    // 인스턴스 맴버
    this.uid = uid;
    this.name = name;

    return this;
}

function clon3(target) {

    target = target || function () { ; };

    // 함수(User3 원형)복사
    var f = target;
    // 프로토타입 맴버 복사
    f.prototype = target.prototype;

    return f;
}

var clonObject3 = new (clon3(User3))('mohwa2', 'mohwaName2');
console.log(clonObject3.uid);
console.log(clonObject3.name);
console.log(clonObject3.getId);


자바스크립트 상속 5 http://mohwaproject.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%83%81%EC%86%8D-5

자바스크립트 상속 6 http://mohwaproject.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%83%81%EC%86%8D-6






프로토타입 맴버에 User3 객체를 연결했으며, "예제 1번"의 상속 계념과 거의 동일하지만 다른점으로는 "객체" 가 아닌 "함수" 를 반환해 구현 했다는 점이다.


function User3(/*string*/uid, /*string*/name) {

    // this 객체 User 생성자(class)의 인스턴스가 아니라면...
    if (!(this instanceof User3)) return null;

    // 인스턴스 맴버
    this.uid = uid;
    this.name = name;

    return this;
}

function clon4(target) {

    target = target || function () { ; };

    var f = function () {
        return this;
    };

    var slice = Array.prototype.slice;
    // User3 객체를 연결
    f.prototype = new target(slice.call(arguments, 1)[0], slice.call(arguments, 1)[1]);

    return f;
}

var clonObject4 = new (clon4(User3, 'mohwa3', 'mohwaName3'))();
console.log(clonObject4.uid);
console.log(clonObject4.name);
console.log(clonObject4.getId);​





5. 새로운 속성을 정의하여 객체 확장하기


Object.defineProperty 메서드(ECMAScript5)를 활용해 객체 속성을 정의한다.



// 속성 정의
var obj1 = {};
Object.defineProperty && Object.defineProperty(obj1, 'datas', {
    value: {
        uid: 'mohwa',
        name: 'mohwaName'
    },
    // 속성 변경 유/무
    writable: true,
    // for in 반복문 검사 유/무
    enumerable: true,
    // 이미 지정한 속성의 설정 변경 유/무
    configurable: false
});

console.log(obj1.datas.uid);
console.log(obj1.datas.name);


var obj2 = {};
// get, set 옵션을 사용 시 value 옵션을 함께 사용할 수 없다.
Object.defineProperty && Object.defineProperty(obj2, 'datas', {
    get: function () {
        return value;
    },
    set: function (newValue) {
        value = newValue;
    }
});

obj2.datas = {};
console.log(obj2.datas.uid);
console.log(obj2.datas.name);

// 여러 개의 속성 한번에 정의
var obj3 = {};
Object.defineProperties && Object.defineProperties(obj3, {
    'datas1': {
        value: {
            uid: 'mohwa1',
            name: 'mohwaName1'
        },
        writable: true
    },
    'datas2': {
        value: {
            uid: 'mohwa2',
            name: 'mohwaName2'
        },
        writable: true
    }
});

console.log(obj3.datas1.uid);
console.log(obj3.datas2.uid);


ECMAScript5 객체 속성 추가

http://dol2156.tistory.com/archive/20120516






6. 객체 속성 열거하기



var propertys = '';
var obj = {
    uid: 'mohwa',
    name: 'mohwaName'
}

// Object.keys 속성 사용(ECMAScript5)
propertys = Object.keys && Object.keys(obj).join(',');

console.log(propertys);

// Object.getOwnPropertyNames 속성 사용(ECMAScript5)
propertys = Object.getOwnPropertyNames && Object.getOwnPropertyNames(obj).join(',');

console.log(propertys);

// for in문 검색 결과(기본)
propertys = (function () {

    var ownPropety = Object.hasOwnProperty;
    var _propertys = [];
    for (var n in obj) {
        if (ownPropety.call(obj, n)) {
            _propertys.push(n);
        }
    }

    return _propertys;
})().join(',');


console.log(propertys);





7. 속성 추가 및 속성 서술자 변경 금지


Object.seal 메서드(ECMAScript5)를 활용해 객체 속성이 추가되는 것은 물론 속성 서술자가 변경되는 것을 막는다.



var obj = {
    uid: 'mohwa',
    name: 'mohwaName'
}

// 속성 추가 및 서술자 변경 금지
// 객체 속성의 추가, 삭제를 막는다.(수정은 가능)
if (Object.seal) {
    Object.seal(obj);
}

try {
    // 수정 됨
    obj.uid = 'new mohwa';
    // 추가 안됨
    obj.uid2 = 'new mohwa';

    console.log('retuls1=' + obj.uid);
    console.log('retuls1=' + obj.uid2);

    // 삭제 안됨
    delete obj.uid;

    console.log('retuls1=' + obj.uid);

}
catch (e) {
    console.log(e);
}

var obj = {
    uid: 'mohwa',
    name: 'mohwaName'
}

// 속성 불변 객체 만들기

// 객체 속성의 모든 기능(추가, 수정, 삭제)를 막는다.
if (Object.freeze) {
    Object.freeze(obj);
}

try {

    // 수정 안됨
    obj.uid = '';

    // 추가 안됨
    obj.uid2 = '';

    console.log('retuls2=' + obj.uid);
    console.log('retuls2=' + obj.uid2);

    // 삭제 안됨
    delete obj.uid;

    console.log('retuls2=' + obj.uid);


}
catch (e) {
    console.log(e);
}




8. 일회성 객체와 네임스페이스


자바스크립트 모듈 과 네임스페이스 http://mohwaproject.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B0%95%EC%A2%8C-10-%EB%AA%A8%EB%93%88-%EA%B3%BC-%EB%84%A4%EC%9E%84%EC%8A%A4%ED%8E%98%EC%9D%B4%EC%8A%A4






9. prototype.bind 함수(주어진 함수의 유효범위를 다룬다)



window.name = 'WindowName';

var objObject = {
    name: 'objObjectName',
    getNewName: function () {
        return (function (that) {
            console.log('result3=' + that.name);
        })(this);
    }
};

if (!Function.prototype.bind) {
    Function.prototype.bind = function (scope) {
             
        var fn = this;
        return fn.apply(scope, arguments);
    }
}

// 유효범위(obj11)
objObject.getNewName();
// 유효범위(window)
objObject.getNewName.bind(this)();




10. 객체 메서드 체인 패턴


자바스크립트 (Singleton, Factory, Chain, Interator) Pattern 구현 http://mohwaproject.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Singleton-Factory-Chain-Interator-Pattern-%EA%B5%AC%ED%98%84





prev 1 ··· 8 9 10 11 12 13 14 ··· 56 next