0

我试图了解 node.js 流中发生的事情的顺序。我正在运行的脚本需要一组名称/电子邮件对,在该集合上运行,为每个集合创建一个 couchdb 条目,然后生成一个 QR 码并将其插入到该 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' }

我想了解的是为什么我以这种半错开的顺序获取日志,而不是一个“沙发图像回复”,然后是一个“成功创建 # 个票证”。

任何帮助都会摇滚!

更新Ahhhh,我正在学习 :) 好的,所有的 forEach 函数都会立即触发。去节点!这是荒谬的。好吧,还有一个问题……

如果图像插入没有错误回复,我如何才能让“#票已成功发布”日志仅触发?我可以将 code.on('end') 放在 couchdb 回调中吗?不不,那是在管道内,这将是非常令人困惑的……我有点迷路了。

4

1 回答 1

2

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);

应该做的伎俩。

于 2014-09-24T15:18:05.127 回答