【问题标题】:Javascript - call two asynchronous functions sequentiallyJavascript - 依次调用两个异步函数
【发布时间】:2017-06-01 10:36:05
【问题描述】:

我有一个类似这样的代码

class foo {
    constructor() {

        // calling a, b, c synchronously
        a().then(
            function(response) {
                b().then(
                    function(response) {
                        c();
                    }, function(error) {
                        // pass
                    }
                );
            }, function(error) {
                // pass
            }
        );
    }

    a() {
        return new Promise(function(fullfill, reject) {

            // x is any function that returns a promise, making the
            // implementation of this function "a" asynchronous
            x().then(
                function(response) {
                    fullfill(response);
                }, function(error) {
                    reject(error);
                }
            );

        });
    }

    b() {
        return new Promise(function(fullfill, reject) {

            // x is any function that returns a promise, making the
            // implementation of this function "b" asynchronous
            x().then(
                function(response) {
                    fullfill(response);
                }, function(error) {
                    reject(error);
                }
            );

        });
    }

    c() {
        // do something
    }

}

基本上,我有两个函数ab,它们都是异步的。 这些函数是异步的,因为它们都调用了一些函数 x,它返回一个 promise(在我的例子中,它是对数据库的查询)。

我需要拨打a,然后是b,然后是c,但要按顺序拨打。一种方法是我在上面的代码中实现的,但它会导致讨厌的嵌套承诺响应。

有没有其他方法可以在不使用以下语法的情况下实现相同的结果(因为如果这是唯一可能的解决方案,那么我可能根本不使用它。

【问题讨论】:

  • @atmd 是的。 abc 是我编写的函数。但是它们都对数据库进行查询,并且这些查询是异步的。而且我无法控制这些查询。
  • @m14 说什么,就做a().then(b).then(c);
  • 如果 x() 有一个 .then() 那么它已经是一个承诺。在这种情况下,不要自己创建承诺,只需执行a() {return x()}。就这样。只有当x() 没有返回承诺(没有.then())时,您才应该自己创建承诺。
  • 顺便说一句,同步!==顺序。你不能同步一个异步函数;但是你可以依次调用多个异步函数……

标签: javascript asynchronous promise


【解决方案1】:

令 seq = [f1,f2,...,fn] 是一个零参数承诺序列 返回函数。构建一个将执行它们的promise p 在 f{i-1} 之后依次调用 fi。

var p = seq.reduce( (p_acc,f) => p_acc.then( ()=>f() ) )

那你可能想做

p.catch(...)

【讨论】:

    【解决方案2】:

    如下所示使用承诺链:

    a().then(resA => {
        // resA is response of function a()
        // Do whatever you want with resA here
        // and then return promise of function b()
    
        return b();
    })
    .then(resB => {
        // resB is response of function b()
        // Do whatever you want with resA here
        // and then return promise of function c()
    
        return c();
    })
    .then(resC => {
        // resC is response of function c()
        // Do whatever you want with resC here
    })
    .catch(err => {
        // Handle any reject/error of functions a, b or c
    });
    

    如果你想将函数 a 和 b 的响应传递到最后,那么你可以按如下方式进行链接:

    a().then(resA => {
        // resA is response of function a()
        // Do whatever you want with resA here
        // and then return promise of function b()
    
        return b().then(resB => { resA: resA, resB: resB });
    })
    .then(res => {
        // res is a object with rsponse of function a() & b()
        // res.resA is response of function a()
        // res.resB is response of function b()
        // Do whatever you want to with the responses here
        // then return promise of function c()
    
        return c().then(resC, { resA: res.resA, resB: res.resB, resC: resC });
    })
    .then(resC => {
        // res is a object with rsponse of function a(), b() & c()
        // res.resA is response of function a()
        // res.resB is response of function b()
        // res.resC is response of function c()
        // Do whatever you want to with the responses
    })
    .catch(err => {
        // Handle any reject/error of functions a, b or c
    });
    

    上面的代码是为演示/解释而精心设计的。它可以用 ES6 减少,如下所示

    a().then(resA => {
        // resA is response of function a()
        // Do whatever you want with resA here
        // and then return promise of function b()
    
        return b().then(resB => { resA, resB });
    })
    .then(res => {
        // res is a object with rsponse of function a() & b()
        // res.resA is response of function a()
        // res.resB is response of function b()
        // Do whatever you want to with the responses here
        // then return promise of function c()
    
        return c().then(resC, Object,assign(res, { resC }));
    })
    .then(resC => {
        // res is a object with rsponse of function a(), b() & c()
        // res.resA is response of function a()
        // res.resB is response of function b()
        // res.resC is response of function c()
        // Do whatever you want to with the responses
    })
    .catch(err => {
        // Handle any reject/error of functions a, b or c
    });
    

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-27
      • 2021-12-05
      • 1970-01-01
      • 1970-01-01
      • 2022-10-14
      • 2012-02-25
      • 2014-08-16
      相关资源
      最近更新 更多