2015-12-30 100 views
1

我努力實現Promises。 (我認爲我明白他們,但我經常得到意想不到的結果,所以也許我不知道。)關於承諾的細節;示例

請考慮這段代碼。

function ap() { 
    return new Promise(function(resolve, reject) { 
    console.log('function ap starting want this'); 
    function ender() { 
     console.log('function ender starting want this'); 
     return resolve('ender'); 
     console.log('after return in ender don\'t want this'); //#1 
    } 
    ender() 
    console.log('after function ender and its resolve ' + 
     'for Promise don\'t want this'); //#2 
    }) // Promise 
} // ap 

console.log('---') 
ap() 
.then(function(result, error) { 
    if (error) console.log ('error ' + error.message) 
    console.log('function ap result result=' + result + 
    ' want this') 
}) 

我已經包含的console.log語句很多地方,並表示我是否希望他們打印,給我的承諾的理解。

我預計:

function ap starting want this 
function ender starting want this 
function ap result result=ender want this 

我不想最後一次通話裏面安德CONSOLE.LOG(//#1),因爲它是經過充分迴歸到讓我離開安德範圍。我的棉絨聲稱它「無法達到」;聽起來一致。

我並不想在ender調用之後調用控制檯(//#2),因爲ender畢竟解決了幾乎所有ap範圍的Promise;退出承諾並退出ap並不奇怪。

我:

function ap starting want this 
function ender starting want this 
after function ender and its resolve for Promise don't want this 
function ap result result=ender want this 

問:這是正確的教訓是什麼?該語言不承認在適用範圍內承諾的重要性。 「回報」足以讓範圍擴大,但不是範圍。 「解決('恩德')」足以解決承諾。 ender調用之後繼續執行鏈,這就是打印不需要的語句的原因。程序員必須發送回調函數的Promise 超出封閉函數的範圍。

繼續假設是真的,我寫了這段代碼。

function bp() { 
    return new Promise(function(resolve, reject) { 
    console.log('function bp starting want this') 
    function ender() { 
     console.log('function ender starting want this'); 
     return resolve('ender'); 
     console.log('after return in ender don\'t want this'); 
    } 
    ender(); return; 
    console.log('after function ender and its resolve ' + 
     'for Promise don\'t want this'); 
    }) // Promise 
} // bp 

它與第一個代碼的不同之處僅在於我在ender調用之後立即添加了一個返回值。通過ender的唯一途徑包括「return resolve('ender')」;如果我在ender調用後立即添加「return」,它會讓我脫離bp範圍,並且一切都可能會好起來。

考慮到不同的函數名稱,我期望得到與我以前預期的相同的結果並獲得了該結果。似乎我的「經驗教訓」可能接近正確的答案。

接下來我寫了這段代碼(請忽略對j的引用;它們讓人分心;我認爲我需要它們來解決後續問題,但這並不是第一次工作,所以使這篇文章變短了):

function cp(i, j) { 
    return new Promise(function(resolve, reject) { 
    console.log('function cp starting   i=' + i + 
     ' j=' + j + ' want this'); 
    function ender() { 
     console.log('function cp ender starting i=' + i + 
     ' j=' + j + ' want this'); 
     i++; 
     let reps = 3; 
     if (i < reps) { 
     cp(i, j) 
     .then(function(result, error) { 
      if (error) { 
      console.log('*** error i=' + i + 
       ' j=' + j + ' msg=' + error.message + 
       ' want this'); 
      return reject(error); 
      } 
      console.log('in cp cp('+ i + ', ' + j + 
      ')  result=' + result + ' want this'); 
      return resolve(result); 
     }) // cp(i) callback 
     console.log('in cp i=' + i + ' j=' + j + '' + 
      ' in ender after reject, resolve, and ' + 
      'callback don\'t want this'); //#3 
     } // if (i < reps) 
     console.log('in cp resolving i=' + i + 
      ' j=' + j + '  want this') 
     return resolve('done'); 
    } // ender 
    ender(); return; 
    console.log('in cp i=' + i + ' j=' + j + 
     ' after ender call and return for cp scope' + 
     ' don\'t want this'); 
    }) // Promise 
} // cp 

它增加了遞歸,並立即跟着ender調用「return」;它刪除了linter標識的無法訪問的代碼;一切都可能順利。

function cp starting   i=0 j=0 want this 
function cp ender starting i=0 j=0 want this 
function cp starting   i=1 j=0 want this 
function cp ender starting i=1 j=0 want this 
function cp starting   i=2 j=0 want this 
function cp ender starting i=2 j=0 want this 
in cp resolving i=3 j=0  want this 
in cp i=2 j=0 in ender after return, resolve, and callback don't want this 
in cp resolving i=2 j=0  want this 
in cp i=1 j=0 in ender after return, resolve, and callback don't want this 
in cp resolving i=1 j=0  want this 
in cp cp(2, 0)  result=done want this 
in cp cp(1, 0)  result=done want this 
function cp result result=done want this 

這就是我希望得到的,除了//#3版畫因爲語言不承認所有的可能性被要麼「拒絕」或覆蓋「解決」內回調塊;它繼續在那個位置不明智地執行命令。

這些代碼位是我繼續遇到麻煩的程序的模型。很快,我希望能夠模擬出令我驚訝的其他行爲。

在更一般的層面上:Promises的第一次使用者經常無法理解Promise?我們如何能夠有更高的信心來適當控制執行流程?在這個詳細程度上解釋什麼資源特別有用?我會感謝在這個更一般的層面上的任何建議。

在此先感謝...

+1

OMG,serioursly ???嘗試發佈相關細節並不是完整的故事。 – dreamweiver

+0

爲什麼你甚至使用'j'? – thefourtheye

+2

像***這樣的問題Promises的第一次使用者經常無法理解Promise?***對Stack Overflow來說過於寬泛。人們可以寫一本關於該主題的書或很長的文章。這個網站的效果最好,一個簡潔的問題在幾個主要不以意見爲基礎的段落中有明確的答案。另外,對於堆棧溢出,要求第三方資源被視爲** off-topic **。這個問題需要清理或關閉。 – jfriend00

回答

2

這裏真正的答案是,拒絕決心只是回調並標註拒絕承諾的/決心。他們不修改原來的JavaScript工作方式,這是你的假設「我不想在ender調用之後調用控制檯,因爲ender(//#2)畢竟解決了Promise,它幾乎全部是AP的範圍;這將會是毫不奇怪退出承諾和退出AP

調用rejectresolve只是意味着你將與承諾工作。這並不意味着你這樣做的功能將立即退出。所以肯定如果你想這樣做 - 使用return

而且這非常相同的與你的下一個例子:

if (i < reps) { 
    cp(i, j) 
    .then(...) 

    console.log(... // you DON'T want this 
} 

好耶,肯定你會得到它,儘管你不想要它。您創建了一個if聲明,其中您執行一些Promise魔術,然後使用console.log。所以JavaScript不關心它是否是Promise - 它只是一個接一個地執行。

如果您閱讀了關於Promises的更多信息,您將會明白它們是純粹的JavaScript,其中包含try-catch,因此如果發生錯誤,它們可以捕獲並調用失敗回調(通常與.catch(function(err){}))。

再次 - 承諾不會修改JavaScript的工作方式!而你所說的一切都是非常符合邏輯的,而且確實應該發生這種確切的方式。這是因爲你期望承諾阻止你的其他代碼,這是不會發生的:)

+0

感謝噸的寬容和答案。我很難理解Promise的意外行爲。他們缺席我所有的書籍。我的網頁搜索沒有找到這個細節。我的熟人圈裏沒有JavaScript專家。我同意其他人的觀點,即在回答特定的語法問題時SO最有效;我不是故意濫用它。我需要另一個指針,例如當我問異步問題時,有人說「檢查藍鳥!」這個人是對的:承諾是好多了,但我希望我有更多的文件。 – BaldEagle

+1

我認爲[Q的文檔](https://github.com/kriskowal/q)可能會有所幫助。這只是Promise的另一個實現。祝你好運! –

+0

再次感謝。我會閱讀Q的文檔。同時,請提供後續問題。我們同意:「/ /你不想要這個」(從你的代碼片段)。什麼觸發這些輸出?它似乎不可能比返回後面的「//#3」更容易到達。導致輸出的語句在語法上與'cp(i,j)'相同,並且所有流量都已經離開了'ender'範圍。困惑。謝謝。 – BaldEagle