(자작) async-to-sync (자바스크립트 비동기 함수 헬퍼)

async-to-sync

async-to-sync는 자바스크립트 비동기 함수를 동기 함수로 바꿔주는 헬퍼 함수이다.
async/await는 물론 Promise를 몰라도 된다!!

왜 async-to-sync를 만들었는가?

드디어 async/await가 ES2017에 추가 되었다(아직 최종 스펙이 나온 건 아니지만).
async/await는 자바스크립트 비동기 함수를 동기 함수로 바꿔주는 기능을 한다.
하지만 여전히 사용하기가 어렵고, 또한 ES2015의 Promise를 알고 있다는 전제 하에 사용이 가능하다.
그래서 비동기 함수를 동기 함수로 만들 때 사용하기 편하려고 만들었다.

시작하기

설치

npm

1
npm i -S async-to-sync

yarn

1
yarn add async-to-sync

사용법

만약 타겟 브라우저/노드의 async/await 및 Promise 지원 여부를 모른다면 아래 링크를 확인하자.
ECMAScript 6 compatibility table | Promise
Node.js ES2015/ES6 | Promise
ECMAScript 2016+ compatibility table | async
Node.js ES2017 support | async
주의!
async-to-sync는 babel-polyfill을 포함하지 않았다.
따라서 babel-polyfill을 사용해야한다면 설치를 하자.
npm

1
npm i -S babel-polyfill

yarn

1
yarn add babel-polyfill

혹은 CDN을 이용하면 된다.
아래 구구절절한 사용 방법 대신 빠르게 사용 방법을 익히고 싶다면 examples를 참조하자.

async-to-sync 모듈을 불러오는 방법

웹팩
async/await & Promise 지원 브라우저인 경우
1
import ats from 'async-to-sync';
async/await & Promise or ES2015 미지원 브라우저인 경우

babel-polyfill 사용이 필수이다.
또한 async-to-sync 모듈을 불러오기 전에 babel-polyfill을 불러와야만 한다.
만약 바벨과 같은 트랜스파일러를 쓰지 않는다면, ES2015 문법 사용은 지양하자. (MS 진영은 암담하기에…)

1
2
import 'babel-polyfill';
import ats from 'async-to-sync/module/no-es2017';
브라우저 (CDN은 지원 예정이니 잠시만 기다리자!)
async/await & Promise 지원 브라우저
1
<script src="node_modules/async-to-sync/browser/es2017/index.min.js"></script>
async/await & Promise or ES2015 미지원 브라우저

babel-polyfill 사용이 필수이다.
또한 async-to-sync 모듈을 불러오기 전에 babel-polyfill을 불러와야만 한다.
만약 바벨과 같은 트랜스파일러를 쓰지 않는다면, ES2015 문법 사용은 지양하자. (MS 진영은 암담하기에…)

1
2
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.23.0/polyfill.min.js"></script>
<script src="node_modules/async-to-sync/browser/no-es2017/index.min.js"></script>
Node.js
async/await & Promise를 지원할 때

만약 import 문법을 쓰고 싶다면 바벨과 같은 트랜스파일러를 이용하자.

1
const ats = require('async-to-sync');
In async/await & Promise or ES2015 not support Node

babel-polyfill 사용이 필수이다.
또한 async-to-sync 모듈을 불러오기 전에 babel-polyfill을 불러와야만 한다.
만약 import 문법을 쓰고 싶다면 바벨과 같은 트랜스파일러를 이용하자.

1
2
require('babel-polyfill');
const ats = require('async-to-sync/module/no-es2017');

어떻게 쓰는가

비동기 함수에는 몇 가지 종류가 있다.

  • setTimeout(or setInterval)
1
2
3
4
5
6
7
8
9
10
11
var a = function() {
setTimeout(function() {
console.log(123);
}, 2000);
};

var b = function(b) {
setTimeout(function() {
console.log(b);
}, 1000);
};
  • AJAX(Asynchronous Javascript And XML)
    bluebird, axios, jQuery slim과 같은 써드 파티들을 사용해도 된다.
    XHR(XMLHttpRequest)이나 fetch를 쓸 때는 Promise를 써야한다.
    then 메소드는 성공 콜백 함수와 같고, catch 메소드는 실패 콜백 함수와 같다.
    주의!
    몇몇 AJAX 요청은 IE9에서 문제가 되지만 이것은 async-to-sync의 문제가 아니다.
    아래 링크를 참조하자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
var fallback = function(e) {
alert('Error: ' + e);
};

var xhr = function(url, method) {
method = method || 'get';
return new Promise(function(res, rej) {
var xhr = new XMLHttpRequest();
xhr.open(method, url, true);
xhr.responseType = "json";
xhr.onreadystatechange = function() {
if(xhr.readyState === 4) { // 4 means request is done.
if(xhr.status === 200) { // 200 means status is successful
res(xhr.response);
} else {
rej(xhr.status);
}
}
};
xhr.send();
});
};

var _fetch = function(url, method, headers, body) {
method = method || 'get';
headers = headers || null;
body = body || null;
return fetch(url, {
method, headers, body
}).then(function(res) {
return res.json({});
});
};

var c = function(url) {
xhr(url).then(function(data) {
console.log(data);
}).catch(function(e) {
fallback(e)
});
};

var d = function(url) {
_fetch(url).then(function(data) {
console.log(data);
}).catch(function(e) {
fallback(e)
});
};

주의!
다음의 규칙들을 따라서 함수를 재작성하자.

  • 함수의 파라미터에 콜백 함수를 추가해주자.
  • 비동기 함수 맨 마지막에 콜백 함수를 실행해주자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 모든 비동기 함수마다 콜백 함수를 파라미터로 추가해줘야한다.
var a = function(cb) {
setTimeout(function() {
console.log(123);
// 비동기 함수의 맨 마지막에는 콜백 함수를 반드시 실행해줘야한다.
cb();
}, 2000);
};

// 콜백 함수는 파라미터 제일 끝 부분에 추가해주자.
var b = function(b, cb) {
setTimeout(function() {
console.log(b);
cb();
}, 1000);
};

var c = function(url, cb) {
xhr(url).then(function(data) {
console.log(data);
cb();
}).catch(function(e) {
fallback(e)
});
};

var d = function(url, cb) {
_fetch(url).then(function(data) {
console.log(data);
cb();
}).catch(function(e) {
fallback(e)
});
};
진짜 사용 방법
ats(Array arrAsync[, Function fallback])
  1. arrAsync의 타입은 배열이다.
    이 배열은 비동기 함수들을 포함하고 있다.
    이 함수들은 동기적으로 실행될 것이다.
  2. fallback의 타입은 함수이며, 필수 사항이 아니다.
    이 함수는 에러 발생시 실행되며, 그 이후에 실행될 함수들의 실행을 모두 멈춰버린다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var arrUrl = [
'https://perfectacle.github.io/mock/test.json',
'https://perfectacle.github.io/mock/test2.json'
];

var arrAsync = [
a,
// 인자를 넘겨주거나 this 값을 바인딩해야할 경우 bind 메소드를 사용하면 된다.
c.bind(null, arrUrl[0]),
// 물론 인자를 넘길 때 ES2015의 arrow function을 사용해도 된다.
// 하지만 이 때는 콜백 함수까지 같이 매개변수 및 인자로 넘겨줘야한다.
cb => b(2, cb),
a,
cb => d(arrUrl[1], cb),
b.bind(null, 33)
];

ats(arrAsync, fallback);

지원하는 플랫폼

ChromeFirefoxIENode.js
Latest ✔Latest ✔9+ ✔6+ ✔