by DevMeetings (Piotrek Koszuliński; @reinmarpl; http://code42.pl)
<script src="jquery-1.6.4.min.js"></script>
<script src="modernizr.custom.js"></script>
<script src="deck.core.js"></script>
<script>
$(function() {
$.deck('.slide');
});
</script>
window === thisthis.test = 1; test; //-> 1var url = require('url'),
utils = require('./utils'),
EventEmitter = utils.EventEmitter,
Model = require('./model');
global !== thisthis.test = 1; test; // -> Reference error (uwaga na testowanie w konsoli Node'a)def czy call?try {
var fn = function () {
throw new Error();
};
}
catch (e) {
console.log('def', e);
}
try {
setTimeout(fn, 1);
}
catch (e) {
console.log('call', e);
}
def czy call?
def, nie call, wyjątek leci w kosmosfs.writeFile('sth', function (err, result) {});process.on('uncaughtException', function (err) {
console.log('ups', err);
});
app.get('/post/:title', function (req, res) {
db.getPostByTitle(req.params.title, function (err, post) {
if (err) throw err;
db.getComments(post.id, function (err, comments) {
if (err) throw err;
res.render({
post: post,
comments: comments
});
});
});
});
fs.readdir(__dirname, function (err, names) {
var l = names.length, opened = 0, content = [];
names.forEach(function (name, i) {
fs.readFile(name, 'utf-8', function (err, c) {
content[i] = c;
if (++opened === l) write();
});
});
var write = function () {
fs.writeFile('lib.js', content.join("\n"), function (err) {
console.log('done');
});
};
});
Więcej:
series(tasks, [callback]) – Run an array of functions in series, each one running once the previous function has completed.parallel(tasks, [callback]) – Run an array of functions in parallel, without waiting until the previous function has completed.waterfall(tasks, [callback]) – Runs an array of functions in series, each passing their results to the next in the array.app.get('/post/:title', function (req, res) {
async.waterfall([
function (callback) {
db.getPostByTitle(req.params.title, callback);
},
function (post, callback) {
db.getComments(post.id, function (comments) {
callback(null, post, comments);
});
}
],
function (err, post, comments) {
if (err) throw err;
res.render({
post: post,
comments: comments
});
}
});
Załóżmy, że mamy asynchroniczną funkcję:
var oneOneSecondLater = function (callback) {
setTimeout(function () {
callback(1);
}, 1000);
};
oneOneSecondLater(function (v) { console.log(v); });
Spróbujmy inaczej:
var maybeOneOneSecondLater = function () {
var callback;
setTimeout(function () {
callback(1);
}, 1000);
return {
then: function (_callback) {
callback = _callback;
}
};
};
maybeOneOneSecondLater().then(function (v) {
console.log(v);
});
Po drobnej reaktoryzacji:
var defer = function () {
var callback = null, _value;
return {
resolve: function (_value) {
value = _value;
callback(value);
callback = undefined;
},
then: function (_callback) {
if (callback === null)
callback = _callback;
else
_callback(value);
}
}
};
var oneOneSecondLater = function () {
var result = defer();
setTimeout(function () {
result.resolve(1);
}, 1000);
return result;
};
oneOneSecondLater().then(callback);
a2p(fs.readFile, __filename, 'utf-8')
(invoke('toUpperCase'))
(console.log)
.end();
var later = function () {
var d = deferred();
setTimeout(function () {
d.resolve(1);
}, 1000);
return d.promise;
};
later().then(function (n) {
console.log(n); // 1
});
Ale promise, to tak naprawdę then, więc prościej:
later()
(function (n) {
console.log(n); // 1
});later()
(function (n) {
return n + 1;
})
(function (n) {
console.log(n); // 2
});
var a2p = deferred.asyncToPromise.call,
ba2p = deferred.asyncToPromise.bind;
a2p(fs.readFile, __filename, 'utf-8')
(function (content) {
// change content
return content;
})
(ba2p(fs.writeFile, __filename + '.changed'));
join(...):
join(p1, p2, p3)
(function (result) {
// result is array of resolved values of p1, p2 and p3.
});
later()(function (n) { throw new Error('error!'); })
(function () {
// never called
}, function (e) {
// handle error;
});
later()(function (n) { throw new Error('error!'); })
.end(function (e) {
// handle error!
});
Konkatenacja plików w katalogu:
all(
// Read all filenames in given path
a2p(fs.readdir, __dirname),
// Read files content
function (files) {
return join(files.map(function (name) {
return a2p(fs.readFile, name, 'utf-8');
}));
},
// Concat into one string
function (data) {
return data.join("\n");
},
// Write to lib.js
ba2p(fs.writeFile, __dirname + '/lib.js')
).end();
W skrócie:
all(
a2p(fs.readdir, __dirname),
invoke('map', function (name) {
return a2p(fs.readFile, name, 'utf-8');
}), join,
invoke('join', "\n"),
ba2p(fs.writeFile, __dirname + '/lib.js')
).end();
Nasz typowy przypadek:
all(
a2p(db.getPostByTitle.bind(db), 't'),
function (post) {
return a2p(db.getComments.bind(db), post.id);
}
)
(function (args) {
res.render({
post: args[0],
comments: args[1]
});
})
.end(function (err) {
//sth
});
Bądź gdybyśmy korzystali z deferred również w bazie:
all(
db.getPostByTitle('t'),
function (post) {
return db.getComments(post.id);
}
)
(function (args) {
res.render({
post: args[0],
comments: args[1]
});
})
.end(function (err) {
//sth
});
> (function () { throw new Error('Ratunku'); }());
Error: Ratunku
at repl:1:22
at repl:1:44
at REPLServer.eval (repl.js:80:28)
at repl.js:178:16
> (function fn() { throw new Error('Ratunku'); }());
Error: Ratunku
at fn (repl:1:24)
at repl:1:46
at REPLServer.eval (repl.js:80:28)
at repl.js:178:16
modules.exportsglobal !== this i osobne scope'y)require()...math.js:
exports.add = function () {
var sum = 0, i = 0, args = arguments, l = args.length;
while (i < l) {
sum += args[i++];
}
return sum;
};
add.js:
var add = require('./math').add;
exports.increment = function (val) {
return add(val, 1);
};
program.js:
var inc = require('./increment').increment;
var a = 1;
inc(a); // 2
'/' lub './', wtedy moduł poszukiwany jest w:
module.paths + require.pathsmodule.paths + NODE_PATH (łączone z: $HOME/.node_modules, $HOME/.node_libraries, $PREFIX/lib/node)#:/www/dmme$ node > module.paths [ '/www/dmme/repl/node_modules', '/www/dmme/node_modules', '/www/node_modules', '/node_modules' ]
sudo npm install -g async/usr/local/lib/node_modules/cd ~ && ln -s /usr/local/lib/node_modules .node_modulesvar exports = {}, module = { exports: exports };
function (exports, module, require) {
// ciało modułu
}.call(exports, module, require);
exports; // publiczne API modułu
require – odpada dynamiczne ładowanie skryptówwebmake app.js app_webmade.jsrequire()app.js z wszystkimi zależnościamirequire()define('alpha', ['require', 'exports', 'beta'],
function (require, exports, beta) {
exports.verb = function() {
return beta.verb();
// Or:
return require('beta').verb();
}
});
module math { export x }var jsdom = require('jsdom'),
doc = jsdom.jsdom('<html><body></body></html>'),
window = doc.createWindow();
window.console = console;
window.run(require('fs').readFileSync('jquery.js', 'utf-8'));
window.run('$("body").append("<p>Kopytko!</p>");');
window.run('console.log(document.innerHTML);');
// -> <html><body><p>Kopytko!</p></body></html>
Alternatywnie:
jsdom.env({
html: '<html><body></body></html>',
src: [
require('fs').readFileSync('jquery.js', 'utf-8'),
'$("body").append("<p>Kopytko!</p>");'
],
done: function (err, window) { console.log(window.document.innerHTML); }
});
// -> <html><body><p>Kopytko!</p></body></html>
// -> <html><body><p>Kopytko!</p></body></html> (WTF?)
What sits between the front-end of a web application and the back-end of an application? The “middle-end”, naturally!
Kyle Simpson @getify
http://blog.getify.com/2010/07/how-to-begin-your-middle-end/
app.get, app.post)pushState()request, response<head>)
/