【问题标题】:Defining then() after promise has been retrieved在检索到 promise 后定义 then()
【发布时间】:2015-11-27 14:04:31
【问题描述】:

我有一个关于在 AngularJS 中将回调函数附加到 Promise 的问题。

假设我有一个带有返回承诺的函数的服务。我调用这个函数并在本地存储承诺。然后我在 promise 上定义了一个回调函数。

var promise = TestService.get();
console.log('We have a promise!');
promise.then(function (result){
  console.log('Here is the result:'+result);
});

在这种情况下,我们面临着潜在的危险情况。如果在我们到达 promise.then(... 之前完成了 promise,则结果不会输出到控制台(直到下一个摘要循环)。

或者,我可以这样写上面的代码:

TestService.get().then(function (result){
  console.log('Here is the result:'+result);
});

我的问题:

第二个示例中的风险是否得到缓解?如果没有,我如何确保在我附加回调之前承诺没有解决? 比是/否更详细的答案将不胜感激:)

【问题讨论】:

  • 您说的是“消化周期”。您是在专门询问 AngularJS 的承诺吗?你的问题到底是什么?
  • 您的两个 sn-ps 之间的行为没有区别。回调将始终被执行,并且始终是异步的。
  • 没错,看问题的第一句话。

标签: javascript angularjs asynchronous angular-promise


【解决方案1】:

您所描述的行为没有发生,这可以通过一个简单的例子看出。这里我们有一个简单的 Promise 工厂,它返回一个立即解析的 Promise。

'use strict';
var make = function() {
  return new Promise(function(resolve, reject) {
    resolve(2);
  });
};

然后我们创建一个新的promise并将它赋值给一个变量

var prom = make();

我们可以根据需要多次调用 .then。这是因为 Promise 是不可变的,我们不会通过在其上链接方法来更改原始值。

prom.then(a => console.log(a));
// 2
prom.then(a => console.log(a));
// 2

【讨论】:

  • then 处理程序始终异步执行。这意味着您的函数将始终在它进入该处理程序之前返回(无论承诺是否已解决或仍处于待处理状态)。
  • @Jonah 感谢您的回答!我的问题是在使用 Karma 对我的服务进行单元测试时出现的。通过在定义回调之前调用$httpBackend.flush(),我会导致我在问题中描述的情况。
【解决方案2】:

假设我有一个带有返回承诺的函数的服务。我调用这个函数并在本地存储承诺。然后我在 promise 上定义了一个回调函数。

不,您没有附加回调。当您调用 then 方法时,您正在执行一种称为 promise chaining 的操作。对 then 的每次调用都会返回一个 new 承诺对象,该对象将解析为前一个承诺返回的值。

例如;

var promise1 = TestService.get();
var promise2 = promise1.then(function(value) {
                  console.log('service resolved: '+value);
                  return "Hello World";
               });
var promise3 = promise2.then(function(value) {
                  console.log(value);
               });
promise3.then(function(value) {
       console.log(value);
});

上面的例子会输出以下内容。

**some value from TestService**
Hello World
undefined

我们不知道谁最初解决了第一个承诺的价值。我们所知道的是该服务返回了一个承诺。从那一刻起,我们可以通过添加更多对 then 的调用来链接 Promise。

在这种情况下,我们面临着潜在的危险情况。如果在我们到达 promise.then(... 之前完成了 promise,则结果不会输出到控制台(直到下一个摘要循环)。

不,何时解决或解决什么摘要并不重要。即使在解决之后,promise 也可以多次调用它的 then 方法。只要它没有被拒绝,它将继续解析为该值。解决或拒绝承诺的决定超出了成功或失败回调的范围。

您可以创建一个promise,将其解析为一个值,等待几个摘要并添加一个处理程序到然后,它仍然会按预期工作。

第二个示例中的风险是否得到缓解?如果没有,我如何确保在我附加回调之前承诺没有解决?

将承诺视为容器。它们将保持您期望的值,您必须调用 then 来获取它。如果由于某种原因该值不可用,您可以使用 error 回调找出原因。 Promise 的 when 方面纯粹是一个异步问题,其想法是让 Promise 隐藏这些问题。

【讨论】:

    【解决方案3】:

    JavaScript 不是多线程的,在您的代码返回之前,您的异步 AJAX 调用实际上并不是由浏览器进行的。

    var promise = TestService.get();
    for (var i= 0;i<100000;i++){
        console.log(i)
    }
    console.log('We have a promise!');
    promise.then(function (result){
        console.log('Here is the result:'+result);
    });
    

    用网络分析仪观看。

    【讨论】:

      猜你喜欢
      • 2017-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-03
      • 1970-01-01
      • 2014-11-26
      • 1970-01-01
      • 2018-12-31
      相关资源
      最近更新 更多