连锁回调的最佳途径?

时间:2018-06-14 09:09:45

标签: node.js

我对在它们之间传递数据时将回调链接在一起的最佳方法提出了疑问。我在下面有一个例子可以使用,但是有一个缺点,即函数必须知道链并知道它们的位置/是否传递回调。

function first(data, cb1, cb2, cb3){
    console.log("first()", data);
    cb1(data,cb2, cb3);
}
function second(data, cb1, cb2) {
    console.log("second()",data);
    cb1(data, cb2);
}
function third(data, cb) {
    console.log("third()",data);
    cb(data);
}
function last(data) {
    console.log("last() ", data);
}
first("THEDATA", second, third, last);  // This work OK
first("THEDATA2", second, last);        // This works OK
first("THEDATA3", second);              // This doesn't work as second tries to pass on a callback that doesn't exit.

我可以想到很多方法,但它们都涉及让被调用的函数知道正在发生的事情。但我的问题是我正在处理的实际功能已经存在,如果我可以避免它,我不想修改它们。所以我想知道我是否错过了如何调用它们的技巧?

4 个答案:

答案 0 :(得分:1)

感谢您的回答,我同意承诺可能是最合适的解决方案,因为它们符合我的要求并提供许多其他优势。

然而,我也想出了如何在不涉及任何额外模块的情况下做我想做的事情。

回顾一下具体问题是:

  • 通过回调链接多个函数(这是第一个函数可以使用其他函数所依赖的非阻塞I / O调用),
  • 在它们之间传递参数(数据)和
  • 不需要修改现有函数以了解它们在回调链中的位置。

我缺少的'技巧'是引入一些额外的匿名回调函数来充当现有函数之间的链接。

// The series of functions now follow the same pattern, which is how they were before
// p1 data object and p2 is a callback, except for last().
function first(data, cb){
    console.log("first()", data);
    cb(data);
}
function second(data, cb) {
    console.log("second()",data);
    cb(data);
}
function third(data, cb) {
    console.log("third()",data);
    cb(data);
}
function last(data) {
    console.log("last() ", data);
}

// And the named functions can be called pretty much in any order without 
// the called functions knowing or caring. 

// first() + last()
first("THEDATA", function (data) { // The anonymous function is called-back, receives the data, 
    last(data);                    // and calls the next function.
});

// first() + second() + last()
first("THEDATA2", function (data) {
    second(data, function (data){
        last(data);
    }); // end second();
}); // end first();

// first() + third()! + second()! + last()
first("THEDATA3", function (data) {
    third(data, function (data){
        second(data, function (data){
            last(data);
        }); // end third();
    }); // end second();
}); // end first();

答案 1 :(得分:0)

承诺是可行的方式,因为它们提供以下好处:

  • 顺序回调链接
  • 并行回调链(种类)
  • 异常处理
  • 轻松绕过对象

一般情况下,Promise会执行某些操作,然后将自己的状态更改为rejected - 失败,或resolved已完成,我们会得到结果。 现在,每个承诺都有方法then(function(result), function(error))。当then()Promiseresolved时,会执行此rejected方法。如果已解决,则执行then()的第一个参数,结果如果Promise被拒绝,则执行第二个参数。

典型的回调链接如下:

示例1:

someMethodThatReturnsPromise()
 .then(function (result) {
  // executed after the someMethodThatReturnsPromise() resolves
  return somePromise;
 }).then(function (result) {
  // executed after somePromise resolved 
 }).then(null, function (e) {
  // executed if any of the promise is rejected in the above chain
 });

如何在第一时间创建Promise?你这样做:

new Promise (function (resolve, reject) {
   // do some operation and when it completes
   resolve(result /*result you want to pass to "then" method*/)
   // if something wrong happens call "reject(error /*error object*/)"
});

有关详细信息,请访问here

答案 2 :(得分:0)

最佳做法是检查你所调用的回叫是否在args中提供。

function first(data, cb1, cb2, cb3){
    console.log("first()", data); // return something
    if(cb1){
        cb1(data,cb2, cb3);
    }
}
function second(data, cb1, cb2) {
    console.log("second()",data); // return something
    if(cb1){
        cb1(data, cb2);
    }
}
function third(data, cb) {
    console.log("third()",data); // return something
    if(cb){
        cb(data);
    }
}
function last(data) {
    console.log("last() ", data); // return something
}
first("THEDATA", second, third, last);  // This work OK
first("THEDATA2", second, last);        // This works OK
first("THEDATA3", second);

这样可以正常工作。 或者,还有更多选项,如Promises和Async library e.tc

答案 3 :(得分:0)

也许您想以这种方式尝试,是的,使用“ Promise”具有更多功能,但是,如果您想要更简单的东西,我们可以这样做,是的,这是没有错误检查的,但是我们当然可以使用try /抓住

function Bersambung(cb){
    this.mainfun = cb            
    this.Lanjut = function(cb){   
        var thisss = this; 
        if(cb){
            return new Bersambung(function(lanjut){
                thisss.mainfun(function(){  
                    cb(lanjut); 
                })
            })                

        } else {
            this.mainfun(function(){});
        }     

    }  
} 


//You can use it like this :

var data1 = "", data2 = "" , data3 = ""

new Bersambung(function(next){ 
    console.log("sebelum async")
    setTimeout(function(){
        data1 = "MENYIMPAN DATA : save data"
        next();
    },1000);

}).Lanjut(function(next){

    if(data1 == ""){
        return; // break the chain
    }

    console.log("sebelum async 2")
    setTimeout(function(){
        console.log("after async")
        console.log(data1);
        next();
    },1000)
}).Lanjut();