2015-11-10 94 views
0

我在嘗試測試事件監聽器中的Promise時遇到了問題。一切都很好,但執行順序。Promise中同步執行的順序

var test = document.querySelector('#test'); 
 
test.addEventListener('click',function(){ 
 
    Promise.resolve().then(function(){ 
 
     throw 'first'; 
 
    }).catch(function(er){ 
 
    \t console.log(er); 
 
    }); 
 
}); 
 
test.addEventListener('click',function(){ 
 
    console.log('second'); 
 
}); 
 
test.click();
<div id="test"></div>

爲什麼不是第一個監聽前面第二收聽完嗎?

+3

'then'的回調異步調用其他代碼。 – zerkms

+0

「完成」是什麼意思? – Bergi

+0

@zerkms你怎麼知道的?你有任何文檔或東西?這是一個錯誤還是預期的行爲? – Lewis

回答

1

它的行爲就像按照標準要求:

  • 否則,如果承諾的[[PromiseState]]內部槽的值是"fulfilled"
    a。讓價值成爲承諾的[[PromiseResult]]內部插槽的價值。 b。執行EnqueueJob("PromiseJobs", PromiseReactionJob, «‍fulfillReaction, value»)
  • 否則,如果承諾的[[PromiseState]]內部槽的值爲"rejected",
    a。讓理由成爲承諾的[[PromiseResult]]內部插槽的價值。 b。執行EnqueueJob("PromiseJobs", PromiseReactionJob, «‍rejectReaction, reason»)
  • 所以,當一個承諾解決或拒絕一個相應的回調被安排在後面跑,異步於當前執行。

    參考文獻:

    +0

    非常感謝規範解釋。我認爲異步執行通常應用於*長期運行*操作(I/O,CPU密集型等)。在這種情況下實施它是沒有意義的。你有什麼想法爲什麼'Promise.then'是異步? – Lewis

    +1

    那麼,我知道它最初是['Promises/A +'](https://promisesaplus.com/)它需要它那樣。我不確定,但是內置的Promise有可能採用了這種行爲。就我個人而言,我不知道他們是異步的技術原因是什麼。另一方面 - 我意識到,即使*如果他們已經解決/拒絕的承諾是同時發生的 - 你仍然不會依賴於此,因爲那樣你就會有兩種不同的行爲。所以也許最初的想法是提供一致的行爲。 – zerkms

    +1

    @zerkms:確切地說,'then'回調*一致*(可靠)異步執行。 – Bergi

    1

    第二個偵聽器不依賴於第一個偵聽器(承諾),因此它們異步工作。你爲什麼要將它們分開?可以簡單地使用下面的代碼

    Promise 
         .resolve() 
         .then(function(){ 
          throw 'first'; 
         }) 
         .catch(function(er){ 
          console.log(er); 
         }) 
         .finally(function(er) { 
          console.log('second'); 
         }; 
        }); 
    
    +0

    我已經知道他們是異步執行的。但是,如果'Promise.then'是同步的,則應該顛倒執行順序。 – Lewis

    +0

    @JaromandaX你沒有明白我的觀點。事件監聽器顯然是異步執行的,但是'Promise.then'。我這麼說是因爲我認爲最好有一個'Promise.then'的同步版本。 – Lewis

    +0

    我試圖理解@Tresdin。好的,我們知道'Promise.resolve()'和'console.log('second')'是兩個異步代碼塊。 'Promise.resolve()'需要更多的時間來執行,所以這就是爲什麼你首先看到'console.log('second')'運行。在這種情況下,如果你希望你的'console.log('second')'在第一個監聽器後自信地運行,你必須把它放在'then,catch或finally'塊中,這就是我們所說的同步執行:)希望我有你的點@Tresdin –