今回は、Qiitaで人気のあるCallback地獄対策の記事で紹介されているaaについて調べてみました。
aaもcoと同様にGeneratorの仕組みを利用して簡単に並列・直列処理フローを記述できるようにするライブラリです。 aaはcoと比べるとthunkify/promisifyが同じライブラリにパッケージされていることと、thunkifyAll/promisifyAllでオブジェクト全体にかけれられるの良いところと思います。 一方で、co.wrapに相当する機能はなく、並列・直列処理フローを利用したyieldableな関数を作るときに少し不便と感じました。
const aa = require('aa'); // callbackを引数にとる関数を持つオブジェクト var callbackObject = { func: function(message, timeout, callback) { setTimeout(function() { console.log(message); callback(null, message); }, timeout); } }; // aa.promisifyAllはオブジェクト全体に対してpromisifyを適用する // promisifyはcallbackを引数にとる関数をPromiseを返却する関数に変換する // Promiseoにはgenerator内でyeild式を適用できる(yeildable) var promisifiedObject = aa.promisifyAll(callbackObject); // aa関数はcoと同様にGenerator(function*(){...})を渡すと、 // yeild式に指定されたPromiseの完了を待ってから処理を再開させる aa(function*() { console.log('--- aa start ---'); // 2つの関数を並列処理する // 並列処理をするにはyeildにArrayもしくはObjectを指定する var response = yield [ promisifiedObject.funcAsync('aa two', 800), promisifiedObject.funcAsync('aa one', 600), ]; console.log("response: " + JSON.stringify(response)); // 2つの関数を直列処理する yield promisifiedObject.funcAsync('aa three', 200); yield promisifiedObject.funcAsync('aa four', 400); // aaを利用した関数の呼び出し(後述) yield wrappedFunction(); console.log('--- aa end ---'); // Generatorでreturnするとaa.then()に指定した関数が実行される return "Generator finished."; // いずれかのPromiseでreject関数が呼ばれると // aa.error()に指定した関数が実行される yield Promise.reject("An error happened."); }).then(function(value){ console.log('--- then start ---'); console.log(value); }).catch((error) => { console.log('--- error start ---'); console.log(error); }); // aaにはco.wrapに相当する機能がないため、 // yieldを利用した関数を定義するにはaa(function*(){})を返却する関数を作る var wrappedFunction = function() { return aa(function* () { console.log('--- wrap start ---'); var response = yield [ promisifiedObject.funcAsync('wrap two', 800), promisifiedObject.funcAsync('wrap one', 600), ]; console.log("wrap response: " + JSON.stringify(response)); yield promisifiedObject.funcAsync('wrap three', 200); yield promisifiedObject.funcAsync('wrap four', 400); console.log('--- wrap end ---'); return yield Promise.resolve(null); }); };
実行結果
$ node aa_generator.js --- aa start --- aa one aa two response: ["aa two","aa one"] aa three aa four --- wrap start --- wrap one wrap two wrap response: ["wrap two","wrap one"] wrap three wrap four --- wrap end --- --- aa end --- --- then start --- Generator finished.