当前位置 主页 > 服务器问题 > win服务器问题汇总 >

    有关Promises异步问题详解(2)

    栏目:win服务器问题汇总 时间:2019-11-10 15:28

    异步操作返回一个promise对象。因此我们在那个promise对象中调用then,并且传给它一个回调函数;then也会返回一个promise。当异步操作结束,它将给promise装上数据。然后(第一次)回调被调用,数据被作为参数传递进去。如果回调不含有返回值,then返回的promise将会立即不带值组装。如果回调返回的不是一个promise,那么then返回的 promise将会立即装载那个数值。如果回调返回一个promise(像例子中的),那么then返回的 promise将等待直到我们回调返回的promise被完全装载。一旦我们回调的 promise被装载,它装载的值(本例中就是data2)将会被提交给then的promise。然后then中的promise装载了data2。等等。听起来有点复杂,但事实上很简单,如果我说的你不能理解,我非常抱歉。我猜我可能不是谈论它的最佳人选。

    用命名的回调替代

    但显然 promises 不是使这个结构扁平化的唯一方法。在写了一篇提到promises解决了厄运的金字塔问题的帖子之后,有个人对该帖评论说……

    我想promises有时是有用的,但是“嵌套”的回调的问题(圣诞树综合症)可以仅用一个命名的函数作为一个参数替代匿名函数的方法平常的处理:

    asyncCall( param1, param2, HandlerCallback );
    function HandlerCallback(err, res){
    // do stuff
    }

    它的例子只是给出了一层深的例子,但它仍是正确的。我们来扩展我前面的例子,使这个看起来容易些。

    命名回调

    // Normal callback usage => PYRAMID OF DOOOOOOOOM
    asyncOperation(handler1);
    function handler1(data) {
      // Do some processing with `data`
      anotherAsync(handler2);
    }
    function handler2(data2) {
      // Some more processing with `data2`
      yetAnotherAsync(handler3);
    }
    function handler3() {
      // Yay we're finished!
    }

    看看上面的代码!他们绝对是对的!它就是一个扁平的结构,但是这里有个问题同样也存在于 我以前从来没有注意过的老的回调例子中:依赖性和复用性。依赖性和复用性是相互关联的可逆类型。一样东西依赖的越少,那么它的复用性就越大。在以上的例子中,handler1依赖handler2,handler2依赖handler3.这就意味着handler1无论出于任何目的都不可在被用除非handler2也呈现出来。假如你不打算重用他们,那么给你的函数命名又有什么意义呢?

    最糟糕的的是handler1都不关心在handler2里面发生了什么事情。它压根就不需要handler2除了和它异步工作。因此,让我们消除这些依赖性然后通过用promise使函数更具复用性。

    链式回调

    asyncOperation().then(handler1).then(handler2).then(handler3);
    function handler1(data) {
      // Do some processing with `data`
      return anotherAsync();
    }
    function handler2(data2) {
      // Some more processing with `data2`
      return yetAnotherAsync();
    }
    function handler3() {
      // Yay we're finished!
    }

    这样看起来是不是好多了?假如另外的函数存在的话,现在handler1和handler2都互不相关了。想看看他们是否真的很棒呢?现在handler1可以被用在不需要handler2的情况下了。相反,handler1被操作以后,我们将可以用另一个handler。

    复用函数

    asyncOperation().then(handler1).then(anotherHandler);
    function handler1(data) {
      // Do some processing with `data`
      return anotherAsync();
    }
    function anotherHandler(data2) {
      // Do some really awesome stuff that you've never seen before. It'll impress you
    }