任何已建立的方便的javascript回调写作风格?

Red*_*dro 1 javascript syntax coding-style callback node.js

回调越来越成为编码的必要条件,尤其是当您考虑Node.JS非阻塞工作方式时.但是很快就会写下大量的协程回调变得难以回读.

例如,想象像这样的金字塔末日:

// This asynchronous coding style is really annoying. Anyone invented a better way yet?
// Count, remove, re-count (verify) and log.
col.count(quertFilter,          function(err, countFiltered) {
    col.count(queryCached,      function(err, countCached) {
        col.remove(query,       function(err) {
            col.count(queryAll, function(err, countTotal) {
                util.log(util.format('MongoDB cleanup: %d filtered and %d cached records removed. %d last-minute records left.', countFiltered, countCached, countTotal));
            });
        });
    });
});
Run Code Online (Sandbox Code Playgroud)

是我们经常看到的东西,很容易变得更加复杂.

当每个函数至少延长几行时,开始分离函数变得可行:

// Imagine something more complex

function mary(data, pictures) {
    // Do something drastic
}

// I want to do mary(), but I need to write how before actually starting.

function nana(callback, cbFinal) {
    // Get stuff from database or something
    callback(nene, cbFinal, data);
}

function nene(callback, cbFinal, data) {
    // Do stuff with data
    callback(nini, cbFinal, data);
}

function nini(callback, data) {
    // Look up pictures of Jeff Atwood
    callback(data, pictures);
}

// I start here, so this story doesn't read like a book even if it's quite straightforward.

nana(nene, mary);
Run Code Online (Sandbox Code Playgroud)

但是,有很多传递变量一直在发生.在其间写入其他功能时,这变得难以阅读.这些函数本身可能过于微不足道,无法证明给自己提供了自己的文件.

Joh*_*yHK 6

使用异步流控制库,如async.它提供了一种简洁的方法来构造需要多个异步调用的代码,同时保持它们之间存在的任何依赖性(如果有的话).

在您的示例中,您将执行以下操作:

async.series([
    function(callback) { col.count(queryFilter, callback); },
    function(callback) { col.count(queryCached, callback); },
    function(callback) { col.remove(query, callback); },
    function(callback) { col.count(queryAll, callback); }
], function (err, results) {
    if (!err) {
        util.log(util.format('MongoDB cleanup: %d filtered and %d cached records removed. %d last-minute records left.', 
            results[0], results[1], results[3]));
    }  
});
Run Code Online (Sandbox Code Playgroud)

这将执行串联的每个功能; 一旦第一个调用它的回调,就调用第二个,依此类推.但您也可以使用parallel或者waterfall与您正在寻找的流量匹配的流量.我发现它比使用承诺更清洁.


Rob*_*ler 5

回调的另一种方法是承诺.

示例:jQuery Ajax.这个看起来很熟悉.

$.ajax({
  url: '/foo',
  success: function() {
      alert('bar');
  }  
});
Run Code Online (Sandbox Code Playgroud)

但$ .ajax也会返回一个承诺.

var request = $.ajax({
  url: '/foo'
});

request.done(function() {
    alert('bar');
});
Run Code Online (Sandbox Code Playgroud)

一个好处是,您可以模拟同步行为,因为您可以使用返回的promise而不是回调$ .ajax.success以及回调和回调的回调....另一个优点是,您可以链接/聚合承诺,如果你愿意,可以为一个promise-aggregate提供错误处理程序.

我发现这篇文章非常有用.它描述了回调,承诺和其他技术的利弊.

一种流行的实现(例如通过AngularJS IIRC使用)是Q.