Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
_get("test1.txt", resume());
_get("test2.txt", resume());
resume()) строятся в стэк, результаты из которого и передаются по очереди в генератор. Это позволяет знать порядок, в котором необходимо отдавать значения, соответственно нужные значения в таком случае поставятся вместо нужных yield.genny можно тут: https://github.com/spion/genny/blob/master/index.jsparallel({
a: function (callback) {
asyncFunction1(args, callback);
},
b: function (callback) {
asyncFunction2(args, callback);
}
}, function (results) {
var smthA = results.a;
var smthB = results.b;
// ...
});
var smthA = yield asyncFunction1(args);
var smthB = yield asyncFunction2(args);
// ...
genny делает ровно то же, что и ваш первый пример: так же выполняет две асинхронные операции перед тем, как продолжить выполнение генератора.co(function *(){
var a = yield get('http://google.com');
var b = yield get('http://yahoo.com');
var c = yield get('http://cloudup.com');
console.log(a.status);
console.log(b.status);
console.log(c.status);
})()
Реализация генераторов, предлагаемая в JavaScript 1.7+, не придерживается черновика ECMAScript 6 — так что вам придется внести некоторые изменения, чтобы заставить примеры работать в Firefox. Если вы хотите запустить эти примеры в Canary, вы можете запускать их в таком же виде, как здесь.
global.sync = function sync( gen )
{
var iterable, resume;
resume = function( err, ret_val )
{
if( err )
{
iterable.throw( err );
return;
}
iterable.next( ret_val );
};
iterable = gen( resume );
iterable.next();
}Canary 34.0.1808.0 метод так же называется throw. Тем не менее, вот пример с корректной обработкой исключений, работающий в Canary: jsfiddle.net/UERy3/var rest = require("../rest");
module.exports = function (app) {
function *vkPush(vkusers, message) {
if (!(vkusers instanceof Array))
throw new Error("vkusers is not array");
var APP_ID = 11111;
var APP_SECRET = "xxxxx";
var uids = [];
try {
var url = 'https://oauth.vk.com/access_token?client_id=' + APP_ID + '&client_secret=' + APP_SECRET + '&grant_type=client_credentials';
var data = yield rest.get(url, vkPush.next); //vkPush.next можно записать как arguments.callee.next
var token = data.access_token;
var url = 'https://api.vk.com/method/secure.sendNotification?access_token=' + token + '&v=5.7&user_ids=' + vkusers.join(',') + '&message=' + encodeURI(message) + '&client_secret=' + APP_SECRET;
var data = yield rest.get(url, vkPush.next);
if (data.response) {
uids = uids.concat(data.response.split(","));
console.log("Received", uids);
}
}
catch (e) {
console.error(e.stack || e);
}
return uids;
}
return function *fn(req, res) {
var table = "notifications";
var user_id = req.user.id;
var client_id = req.user.id;
var id = +req.body.id || +req.query.id;
// Для асинхронных операций
var data = {};
app.db.brodie("Query1", function (err, data) {
data.query1 = data;
}.async());
app.db.brodie("Query2", function (err, data) {
data.query2 = data;
}.async());
app.db.brodie("Query3", function (err, data) {
data.query3 = data;
}.async());
// здесь будет остановка до тех пор пока все запросы не отработают
yield true;
try {
switch (req.method) {
case "GET":
var rows = yield app.db.brodie.query("SELECT * FROM ?? WHERE client_id=? ORDER BY date DESC", [table, client_id], fn.next);
res.send(rows);
break;
case "PUT":
var message = req.body.text;
var data = {
client_id: client_id,
user_id: user_id,
text: message,
received: 0,
date: new Date()
}
var vkusers = yield app.db.brodie.query("SELECT * FROM notification_users WHERE client_id=? AND type='vk'", [client_id], fn.next);
var receiveUids = yield vkPush.run(vkusers, message);
if (receiveUids.length)
yield app.db.brodie.query('UPDATE notification_users SET last_send=NOW() WHERE uid IN (?) AND type="vk" AND client_id=?', [receiveUids, client_id], fn.next);
data.received = receiveUids.length;
var result = yield app.db.brodie.query("INSERT INTO ?? SET ?", [table, data], fn.next);
var rows = yield app.db.brodie.query("SELECT * FROM ?? WHERE id=?", [table, result.insertId], fn.next);
res.send(rows[0]);
break;
default:
res.send(500);
break;
}
}
catch (e) {
console.error(e.stack || e);
}
}.fn();
}
Отказываемся от коллбэков: Генераторы в ECMAScript 6