2016-09-21 120 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 
}));