developer tip

비동기 nodejs 모듈 내보내기

optionbox 2020. 12. 5. 09:39
반응형

비동기 nodejs 모듈 내보내기


모듈 내보내기를 구성하는 가장 좋은 방법이 무엇인지 궁금합니다. 아래 예에서 "async.function"은 FS 또는 HTTP 요청 일 수 있으며 예를 위해 단순화되었습니다.

다음은 예제 코드 (asynmodule.js)입니다.

var foo = "bar"
async.function(function(response) {
  foo = "foobar";
  // module.exports = foo;  // having the export here breaks the app: foo is always undefined.
});

// having the export here results in working code, but without the variable being set.
module.exports = foo;

비동기 콜백이 실행 된 후에 만 ​​모듈을 내보내려면 어떻게해야합니까?

실제 사용 사례에 대한 빠른 메모 편집 : fs.exists () 콜백에서 nconf ( https://github.com/flatiron/nconf ) 를 구성하는 모듈을 작성하고 있습니다 (즉, 구성 파일을 구문 분석하고 nconf 설정).


foo선언이 내부에있는 동안 함수 외부에 있기 때문에 내보내기가 작동하지 않습니다 . 그러나 내보내기를 내부에 넣으면 모듈을 사용할 때 내보내기가 정의되었는지 확인할 수 없습니다.

비동기 시스템으로 작업하는 가장 좋은 방법은 콜백을 사용하는 것입니다. 콜백을 가져 오려면 콜백 할당 메서드를 내보내고 비동기 실행시 호출해야합니다.

예:

var foo, callback;
async.function(function(response) {
    foo = "foobar";

    if( typeof callback == 'function' ){
        callback(foo);
    }
});

module.exports = function(cb){
    if(typeof foo != 'undefined'){
        cb(foo); // If foo is already define, I don't wait.
    } else {
        callback = cb;
    }
}

다음 async.function은 비동기 호출을 상징하는 자리 표시 자입니다.

메인에서

var fooMod = require('./foo.js');
fooMod(function(foo){
    //Here code using foo;
});

다중 콜백 방법

모듈을 두 번 이상 호출해야하는 경우 콜백 배열을 관리해야합니다.

var foo, callbackList = [];
async.function(function(response) {
    foo = "foobar";

    // You can use all other form of array walk.
    for(var i = 0; i < callbackList.length; i++){
        callbackList[i](foo)
    }
});

module.exports = function(cb){
    if(typeof foo != 'undefined'){
        cb(foo); // If foo is already define, I don't wait.
    } else {
        callback.push(cb);
    }
}

다음 async.function은 비동기 호출을 상징하는 자리 표시 자입니다.

메인에서

var fooMod = require('./foo.js');
fooMod(function(foo){
    //Here code using foo;
});

약속 방법

Promise를 사용하여 해결할 수도 있습니다. 이 메서드는 Promise의 디자인에 따라 다중 호출을 지원합니다.

var foo, callback;
module.exports = new Promise(function(resolve, reject){
    async.function(function(response) {
        foo = "foobar"

        resolve(foo);
    });
});

다음 async.function은 비동기 호출을 상징하는 자리 표시 자입니다.

메인에서

var fooMod = require('./foo.js').then(function(foo){
    //Here code using foo;
});

Promise 문서 참조


또 다른 접근 방식은 변수를 개체 내부에 래핑하는 것입니다.

var Wrapper = function(){
  this.foo = "bar";
  this.init();
};
Wrapper.prototype.init = function(){
  var wrapper = this;  
  async.function(function(response) {
    wrapper.foo = "foobar";
  });
}
module.exports = new Wrapper();

이니셜 라이저에 오류가있는 경우 최소한 콜백을 중단하는 대신 초기화되지 않은 값을 얻습니다.


약속을 사용하여 ES6 답변 :

const asyncFunc = () => {
    return new Promise((resolve, reject) => {
        // Where someAsyncFunction takes a callback, i.e. api call
        someAsyncFunction(data => {
            resolve(data)
        })
    })
}

export default asyncFunc

...
import asyncFunc from './asyncFunc'
asyncFunc().then(data => { console.log(data) })

또는 Promise 자체를 직접 반환 할 수 있습니다.

const p = new Promise(...)
export default p
...
import p from './asyncModule'
p.then(...)

Promise를 사용할 수도 있습니다.

some-async-module.js

module.exports = new Promise((resolve, reject) => {
    setTimeout(resolve.bind(null, 'someValueToBeReturned'), 2000);
});

main.js

var asyncModule = require('./some-async-module');

asyncModule.then(promisedResult => console.log(promisedResult)); 
// outputs 'someValueToBeReturned' after 2 seconds

다른 모듈에서도 동일한 일이 발생할 수 있으며 예상대로 해결됩니다.

in-some-other-module.js

var asyncModule = require('./some-async-module');

asyncModule.then(promisedResult => console.log(promisedResult)); 
// also outputs 'someValueToBeReturned' after 2 seconds

promise 객체는 한 번 생성 된 다음 노드별로 캐시됩니다. 각각 require('./some-async-module')은 동일한 개체 인스턴스를 반환합니다 (이 경우 Promise 인스턴스).


ES7 접근 방식은 module.exports에서 즉시 호출되는 비동기 함수 입니다.

module.exports = (async function(){
 //some async initiallizers
 //e.g. await the db module that has the same structure like this
  var db = await require("./db");
  var foo = "bar";

  //resolve the export promise
  return {
    foo
  };
})()

나중에 await로 필요할 수 있습니다.

(async function(){

  var foo = await require("./theuppercode");
  console.log(foo);
})();

다른 답변은 부분 답변으로 보였고 저에게 효과가 없었습니다. 이것은 다소 완전한 것 같습니다.

some-module.js

var Wrapper = function(){
  this.callbacks = [];
  this.foo = null;
  this.init();
};
Wrapper.prototype.init = function(){
  var wrapper = this;  
  async.function(function(response) {
    wrapper.foo = "foobar";
    this.callbacks.forEach(function(callback){
       callback(null, wrapper.foo);
    });
  });
}
Wrapper.prototype.get = function(cb) {
    if(typeof cb !== 'function') {
        return this.connection; // this could be null so probably just throw
    }
    if(this.foo) {
        return cb(null, this.foo);
    }
    this.callbacks.push(cb);
}
module.exports = new Wrapper();

main.js

var wrapper = require('./some-module');

wrapper.get(function(foo){
    // foo will always be defined
});

main2.js

var wrapper = require('./some-module');

wrapper.get(function(foo){
    // foo will always be defined in another script
});

참고 URL : https://stackoverflow.com/questions/20238829/asynchronous-nodejs-module-exports

반응형