管理Meteor中的异步回调

Managing asynchronous Callbacks in Meteor

本文关键字:异步 回调 Meteor 管理      更新时间:2023-09-26

我使用的是Meteor 1.*和Iron Router 1.*.

我在Meteor中的服务器端使用Node.js调用,在Meteol方法之外,特别是在服务器端Iron Router路由中。

到目前为止,路线内部的一部分代码看起来类似于以下内容:

  fs.mkdir(filebox, function (e) {
    if(!e || e.code === 'EEXIST') {
      fs.writeFile(file1, function (err) {
        if (err) throw err;
        fs.writeFile(file2, function (err) {
          if (err) throw err;
          fs.writeFile(file.3, function (err) {
            if (err) throw err;
            ExternalLibrary.do_something_(file1, function (err, buffer) {
              if (err) throw err;
              ExternalLibrary.do_something_(file2, function (err, buffer) {
                if (err) throw err;
                ExternalLibrary.do_something_(file3, function (err, buffer) {
                  if (err) throw err;
                  some_object = { first: file1, second: file2 }
                  ExternalLibrary.do_something_else_(some_object, function (err, buffer) {
                    if (err) throw err;
                    fs.readFile(file1, function (err, data) {
                      if (err) throw err;
                      res.write(data);
                      res.end();
                    });
                  });
                });
              });
            });
          });
        });
      });
    } else {
      console.log(e);
    }
  });

我的问题是,我需要向fs.write和ExternalLibrary添加更多的调用,并进一步使这些调用成为条件调用。

看起来我要进入回叫地狱了。

关于回调

我知道Meteor使用了Coroutines(或纤维,或连续体),但我对它的工作原理一无所知。在Meteor方法中,我们可以选择使用Meteor.wrapAsync.

我读过一些关于Node.js Promises和Generators的文章。特别是我正在试用frozeman/q-meter库。

问题

什么是"压平"这棵树并将自己从回调地狱中拯救出来的最佳方法?我想要一个允许条件方法调用的解决方案。例如,我最终需要在上面的代码示例中添加以下内容:

if (some_condition === true) {
  // call this method or node function
  fs.writeFile(file4, function (err) {
    fs.writeFile(file5, function (err) {
      // do something
    }
  }
}
else {
  // call this method or node function
  fs.writeFile(file6, function (err) {
    fs.writeFile(file7, function (err) {
      // do something
    }
  }
}

我最终使用Promises作为解决方案。我使用了Kris kriskowal/Q的优秀Q库。特别是Meteor的包装是frozeman/q-meter。

以下是代码:

makeDirectory(filebox)
  .then(function () {
    console.log('in write file function');
    return writeFile(file1, data);
  })
  .then(function () {
    console.log('in write file function');
    return writeFile(file2, data);
  })
  .then(function () {
    console.log('in write file function');
    return writeFile(file3, data);
  })
  .then(function () {
    console.log('in external lib function');
    return ExternalLibrary._do_something(file1, data1, output1);
  })
  .then(function () {
    console.log('in external lib function');
    return ExternalLibrary._do_something(file2, data2, output2);
  })
  .then(function () {
    console.log('in external lib function');
    return ExternalLibrary._do_something(file3, data3, output3);
  })
  .then(function () {
    console.log('in concat function');
    return ExternalLibrary.cat(fileToCat, outputCat);
  })
  .then(function () {
    console.log('in read file function');
    return readFile(outputCat);
  })
  .then(function (result) {
    console.log('in the response function');
    res.write(result);
    res.end();
  })
  .catch(function (error) {
    console.log('darn error: ', error);
  })
  .done(function (result) {
    console.log('done');
  });

每个.then中的External Library和函数调用都返回一个延迟的promise,其输出可以在前面的.then函数调用中使用。

帮助我开始的几个链接:

  • 承诺的魔术师指南

  • Node.js中的承诺与Q

  • kriskowal/q API参考

  • Promise反模式