Promise .then(async())与.then(function(){return async()})

时间:2016-11-03 17:20:57

标签: javascript node.js asynchronous promise

我试图弄清楚为什么会发生以下行为,以及可能带来的好处。使用bluebird作为承诺实现。

angular.module('App', [])
  .config(['$provide', function($provide) {

    $provide.decorator('$controller', [
      '$delegate', 'sameInitService',
      function controllerDecorator($delegate, sameInitService) {

        return function(constructor, locals) {
          sameInitService.init(locals.$scope);
          return $delegate(constructor, locals, true);
        }
      }

    ]);
  }])

输出:

printValue = function (value){
   return new Promise(function(resolve, reject){
      console.log(value);
      resolve(value)
   });
}

describe.only('promises', function(){
   it('prints values with then', function(done){
      printValue(1)
      .then(printValue(2))
      .then(function(value){
         console.log('then value: ', value);
      })
      .then(done())
   });

   it('prints values with return', function(done){
      printValue(1)
      .then(function(){
         return printValue(2);
      })
      .then(function(value){
         console.log('return value: ', value);
      })
      .then(done())
   });

});

为什么第一个测试会保留原始承诺的值,当第二个测试从第二个承诺中获取值时?这是否意味着使用1 2 then value: 1 1 2 return value: 2 仅在您不将参数传递给函数时才有效?还是有办法使用上面的语法传递参数?

2 个答案:

答案 0 :(得分:1)

这不容易看到。

在第一部分中,您有:

printValue(1)
      .then(printValue(2))
      .then(function(value){
         console.log('then value: ', value);
      })

你知道,你实际上正在调用printValue(2)并且在你调用它时立即执行它,它不会等待调用前面的函数并且它们的承诺被解决。虽然printValue返回Promise,但.then期望一个函数在调用时返回Promise (或只是返回值的函数)。

所以在.then(printValue(2))中,.then收到一个非函数值,它只是忽略它并转到链中的下一个函数。

您可以尝试这样做以查看:

printValue(1)
    .then("hello!")
    .then(function (val) {
        console.log("got " + val)
    });

所以,它与你所拥有的完全相同,你只需要一个返回一些东西的函数,这里我们只用一个值替换它!

你也可以试试这个:

var printValue = function (value){
    return new Promise(function(resolve, reject){
        console.log("called " , value)
        setTimeout(function () {
            console.log("resolving ", value);
            resolve(value)
        }, value*1000);
    });
}

你会在这里看到:

printValue(1)
        .then(printValue(2))
        .then(function (val) {
            console.log("got " + val)
        });

printValue(1)printValue(2)同时执行。一秒钟后,printValue(1)将解决并打印got 1

答案 1 :(得分:1)

希望我能提供帮助。
为什么第一次测试保留原始承诺的价值?
- 因为它已经解析了util,它找到了一个可以解决它的函数 - 为了使承诺得到解决,它需要找到一种传递解决值的正确方法 要修复您的第一个场景,您需要执行以下操作:

printValue(1)
  .then(printValue)      
  .then(function(value){
     console.log('then value: ', value);
  })

因此,当第一个printValue(原始)得到解析时,它会将值传递给第二个printValue。
你可以传递更多参数的方法是使用咖喱。采用以下示例(使用 ramda ):

'use strict';
const Promise = require('bluebird');
const R = require('ramda');

const printValue = R.curry(function (value){
   return new Promise(function(resolve, reject){
      console.log(value);
      resolve(value)
   });
});

const printSum = R.curry(function (val1, val2){
   return new Promise(function(resolve, reject){
       const r = val1 + val2;
      console.log(r);
      resolve(r)
   });
});     

printValue(1)
.then(printSum(R.__)(3))      
.then(function(value){
    console.log('then value: ', value);
})

因此,假设您想将printValue(原始)的结果与另一个数字相加,使用咖喱与Ramda,您可以指定 R .__ ,这将取值printValue的结果,你仍然可以在这种情况下传递和额外参数 3