我试图了解node.js流中发生的事情的顺序。我正在运行的脚本获取一个名称/电子邮件对的集合,在该集合上运行,为每个集合创建一个couchdb条目,然后生成一个二维码并将其插入该couchdb条目的中。
这是代码:
/*
* This script takes a collection of names/emails and creates tickets for them.
*/
// Connect to Couch.
var db = require('nano')('https://' + process.env.USER + ':' + process.env.PASS + '@' + process.env.COUCH);
// Load QR Generator.
var qr = require('qr-image');
// Who to email?
var people = [
{ name: 'Katie', email: 'katie@*****.com' },
{ name: 'Alex', email: 'alex@*****.com' },
{ name: 'Kelsey', email: 'kelsey@*****.com' }
];
var tix = 0;
// For Each preson in the above list,
people.forEach(function (person, index, array) {
// (1) assemble a grit-ticket doc for couch,
var ticket = {
"name": person.name,
"email": person.email,
"purchaser": "complimentary",
"type": "ticket"
};
// (2) insert that doc into CouchDB,
db.insert(ticket, function (error, doc, headers) {
if (error) return console.log("Couch Error: ", error, "Headers: ", headers);
// (3) make a QR code,
var code = qr.image('https://tedxgramercy.com/attendee?id=' + doc.id, { type: 'png' });
// (4) add that QR code to the doc,
code.pipe( db.attachment.insert(doc.id, 'qr-code.png', null, 'image/png', { rev: doc.rev }, function (err, reply) {
if (err) { return console.log("Couch image error: ", err) }
console.log("Couch image reply: ", reply);
}) );
code.on('end', function (error) {
if (error) { return console.log('QR Submition', [error]) }
tix += 1;
// (5) Report out success.
console.log(tix + " tickets created successfully.");
});
});
});
当我运行这个脚本(有6封电子邮件,而不仅仅是3封)时,我得到的是:
$ node makeTix.js
1 tickets created successfully.
2 tickets created successfully.
3 tickets created successfully.
4 tickets created successfully.
5 tickets created successfully.
Couch image reply: { ok: true,
id: '8e15d0676ec8d9f686ebbd38237a',
rev: '2-f03610b92d3461fc9c167f2405e7a2d0' }
6 tickets created successfully.
Couch image reply: { ok: true,
id: '8e15d0676ec8d9f8f686ebbd3823806e',
rev: '2-eb0f676e4ed6f7203420a4864357e3f8' }
Couch image reply: { ok: true,
id: '8e15d0676ec8d9f8f686ebbd38236158',
rev: '2-038c68f6d57b1925c0353fca3b2d59c1' }
Couch image reply: { ok: true,
id: '8e15d0676ec8d9f8f686ebbd382364a7',
rev: '2-9a19a3cd4b8cff2ae2b38cf000dd0aaf' }
Couch image reply: { ok: true,
id: '8e15d0676ec8d9f8f686ebbd38236fb4',
rev: '2-40c0ccc77c07f470424958e6d6e88a9b' }
Couch image reply: { ok: true,
id: '8e15d0676ec8d9f8f686ebbd38236174',
rev: '2-ac78e326b9898d4a340228faa63167e1' }
我所想理解的是,为什么我以这种半交错的顺序获取日志,而不是一个"沙发图片回复",然后是一个"#成功创建的门票"
任何帮助都会动摇!
更新啊,我正在学习:)好的,所以所有的forEach函数都会同时启动。Go Node!这太荒谬了。好吧,还有一个问题。。。
如果图像插入有无错误回复,我如何才能让"#tickets posted successfully"日志启动?我可以把代码.on('end')放在couchdb回调中吗?不,不,那是在管道里,那会非常令人困惑。。。。我有点迷路了。
Node.js是异步的,这就是您看到这种行为的原因,流与此无关。(流部分归功于MatthewBakaitis)。
每一个回调(或者我应该说,每一个异步函数)基本上都是"嘿,电脑,完成后再打电话给我",这样一切都会同时发生(从用户的角度来看)。ForEach是异步的,db.insert也是,所以在你的代码中发生的基本上是:
//For each people, send a request to the computer to do that function
people.forEach(function (person, index, array) {
//Synchronous part, then
//Hey, send this data to the db for me, and call me when you re done
db.insert(ticket, function (error, doc, headers) {
//Once data is inserted
//Synchronous part
//When pipe happen, do this
code.pipe
//When finished, do this
code.on('end'
因此,对于这六个人,发生的是:
forEach start function for people 1
forEach start function for people 2
forEach start function for people 3
forEach start function for people 4
forEach start function for people 5
In the meantime, function has ended for 1, so execute the callback
forEach start function for people 1
function has ended for 2, so execute the callback
function has ended for 3, so execute the callback
function has ended for 4, so execute the callback
function has ended for 5, so execute the callback
function has ended for 6, so execute the callback
这有点难以理解,你只需要接受每件事都会在同一时间完成。
更新:
尽管forEach是异步的,但在让代码继续之前,它会将代码"锁定"到内部发生的任何事情,所以:
forEach(function (element) {
//Asynchronous code and calculing tx
});
console.log(tx + ' ticket created successfully);
应该做到这一点。