2016-09-21 118 views
1

这基本上是我的代码,使用q在另一个承诺调用承诺,有条件

let d = Q.defer(); 
let result = { 
    name: 'peter' 
}; 

d.resolve(result); 
return d.promise; 

不过,我现在需要执行基于特定条件的一个步骤。这一步调用另一个也返回承诺的对象。所以我有嵌套承诺,如果这是正确的术语。

事情是这样的:

let d = Q.defer(); 
let result = { 
    name: 'peter' 
}; 

if (someParameter) { 
    otherService.getValue() // Let's say it returns 'mary' 
     .then((res) => { 
      result.name = res; 
     }); 
} 

d.resolve(result); 
return d.promise; 

然而,这并不工作(在name属性仍是 '彼得')。可能是因为我内心的承诺在以后的时间里解决了?

我也试过这个,但它不起作用,如果我打电话给其他服务,它返回一个承诺。它确实工作,如果我只是设置的值:

let d = Q.defer(); 
let result = { 
    name: 'peter' 
}; 

d.resolve(result); 
return d.promise 
    .then((data) => { 
     if (someParameter) { 
      // Works 
      data.name = 'john'; 

      // Doesn't work 
      otherService.getValue() 
       .then((res) => { 
        data.name = res; 
       }); 
     } 

     return data; 
    }); 

这里的名称将是'约翰',而不是'玛丽'。

很明显,我误解了承诺,但我无法把头绕在它周围。

+0

看一看[在承诺的if-else流(http://stackoverflow.com/q/26599798/1048572) – Bergi

回答

1

承诺控制流程是... 好玩

无论如何,你几乎在那里,你可以嵌入一个PromisePromise以及链接它们。但是,如果你把它们嵌入,你必须return嵌入式Promise链:

let d = Q.defer(); 
let result = { 
    name: 'peter' 
}; 

d.resolve(result); 
return d.promise 
    .then((data) => { 
     if (someParameter) { 

      // Should work now that we return the Promise 
      return otherService.getValue() 
       .then((res) => { 
        data.name = res; 
        // And we have to return the data here as well 
        return data; 
       }); 
     } 

     return data; 
    }); 

Promiseresolve可取的值或其他Promise,它会处理的流程。所以,当我们在then之内return时,我们返回的值可以是另一个Promise或者只是一个值。机器会照顾我们的包装。

+0

你代码正在工作,但过于复杂,我不得不认为它没有用。 – Bergi

+0

@Bergi对不起,你有这种感觉。我只是复制了OP,以免进一步混淆作者。代码可以更具表现力,是的。由于该帖子是关于Promise控制流程的,所以有必要展示一个完整的示例。在我看来,作者对嵌入的承诺等感到困惑。 –

+0

它很复杂,但同时我重构了它。另外,我的例子在我们的实际代码中比较微不足道。但这个答案向我解释了我做错了什么。 – Peter

2

不推荐使用延迟。如果有的话,你应该使用Q.Promise构造函数,但你甚至不需要它。只需使用Q function即可创建一个满足您的价值的承诺。

现在你可以(也应该)简化您的代码

let d = someParameter ? otherService.getValue() : Q('peter'); 
return d.then(res => ({ 
    name: res 
}));