代码之家  ›  专栏  ›  技术社区  ›  Alexander Solonik

避免使用nodejs在承诺中回调地狱

  •  1
  • Alexander Solonik  · 技术社区  · 7 年前

    我已经在nodejs中用promises编写了大约六个函数,我真的想发布所有的代码,相反,我将发布一个模拟的示例,这样我可以简洁地封装我的问题。假设我有两个功能:

    foo = () => {
        return new Promise( ( r , rj ) => {
           setTimeout( () => {
                 r('DONE');
           }, 3000 );
        }); 
    }  
    

    bar = () => {
        return new Promise( (r , rj) => { r('ALL DONE !') } )
    }
    

    现在,我想避免回调地狱,并执行以下操作:

    foo().then( (resp) => console.log(resp) ).bar()
    

    相反,我不得不做的是:

    foo().then( (resp) => { console.log(resp); bar() } )
    

    所以基本上在我的生产代码中,我有如下的内容,到目前为止(只是给你一个想法):

    let uploadToVault = ( INPUT_DIR , VOLT_CRED ) => {
    
        INPUT_DIRECTORY = INPUT_DIR;
        VOLT_CREDENTIALS = VOLT_CRED;
    
        volt_APILogin().then( () => {
            volt_getProduct().then( () => {
               volt_CreatePresentation().then( (resp) => {
                    console.log(resp);        
                    volt_uploadSlides().then( (resp) => {
                        console.log(resp);
                        volt_bindSlide().then( (resp) => {
                            console.log(resp);
                        });
                    });
               });  
            });
        });
    }
    

    现在,与在回调中写入相比,我如何以更多的链格式写入此内容呢?

    2 回复  |  直到 7 年前
        1
  •  4
  •   Sami Hult    7 年前

    我们的想法是永远兑现承诺:

    volt_APILogin()
    
        .then(() => {
            return volt_getProduct();
        })
        .then(() => {
             return volt_CreatePresentation();
        })
        .then((resp) => {
             console.log(resp);        
             return volt_uploadSlides();
        })
        .then((resp) => {
             console.log(resp);
             return volt_bindSlide();
        })
        .then((resp) => {
             console.log(resp);
             return Promise.resolve('just for fun');
        })
        .then((resp) => {
             console.log("This round is", resp);
        });
    

    然后,如果有中间值需要在链下使用,只需将它们收集到链外的变量即可。

        2
  •  2
  •   busyfingers    7 年前

    一个技巧是检查异步/等待语法。它基本上使编写类似于同步代码的异步代码成为可能。

    所以,如果你有这个功能:

    bar = () => {
        return new Promise( (r , rj) => { r('ALL DONE !') } )
    }
    

    然后你可以这样称呼它:

    let fizz = async () => {
        const result = await bar();
        console.log(`Bar said: ${result}`);
    };
    

    对于错误处理,将等待的函数调用包装在一个try catch块中:

        try {
            const result = await bar();
            console.log(`Bar said: ${result}`);
        } catch {
            // Handle the error
        }
    

    查看此链接了解更多信息: https://javascript.info/async-await (或者只需谷歌“JS Async Wait”,你就会发现更多的东西:)