簡體   English   中英

我怎樣才能消除這些嵌套的承諾?

[英]How can I eliminate these nested Promises?

我讀過你應該避免JavaScript 中的嵌套承諾,因為它們往往是一種反模式,但我無法弄清楚如何在我的特定用例中避免它們。 希望比我更有經驗的人能看出我哪里出錯了? 任何建議將不勝感激!

本質上,我正在異步檢索一些數據,處理它並捕獲可能的錯誤,然后異步保存一些數據。 這是一個非常簡單的例子:

class Foo {
  changeName(path, newName) {
      this.getPage(path) // AJAX call, returns a promise with type Page,
                         //  may throw an Error if the page does not exist.
        .then(page=> {
          // Some modifications are made to page, omitted here
          return page
        })
        .catch(e=>{
          if(e instanceof PageDoesNotExistError) {
            return new Page();
          }
        })
        .then(page=> {
          page.name = newName;
          this.savePage(path, page); // ******
          // I want my outer changeName method to return this ^ promise,
          // or at least a promise that will resolve when this promise
          // resolves, with the same value.
        })
  }
}

我怎樣才能讓changeName返回一個將使用this.savePage的值(標有//******的行)解析的承諾,以便我可以在其他地方做這樣的事情:

myFooInstance.changeName('/path', 'New Name').then(page=> {
  // Do something with the returned saved page
});

我怎樣才能讓 changeName 返回一個可以用 this.savePage 的值解析的承諾

返回來自then處理程序的承諾savePage返回。 這會將then創建的 promise 解析為來自savePage ,這意味着then創建的 promise 將根據savePage執行或拒絕執行。 (如果您有興趣,可以在我的博客文章中詳細了解該術語。)

.then(page=> {
    page.name = newName;
    return this.savePage(path, page);
})

另外,您已經說過您希望調用者能夠對changePage的返回值使用承諾,但您沒有從changePage返回任何內容。 您需要在整個結構前添加return ,以便返回最終的承諾。

changeName(path, newName) {
    return this.getPage(path) // AJAX call, returns a promise with type Page,
    // ...

(有關完整版本,請參見下文。)


旁注:您在此處等待發生錯誤:

.catch(e=>{
    if(e instanceof PageDoesNotExistError) {
        return new Page();
    }
})

如果e不是PageDoesNotExistError的實例,則您將拒絕轉換為值為undefined ,因為在這種情況下您的catch處理程序不會返回顯式值。 如果你想傳播錯誤,你需要用throw ereturn Promise.reject(e)來做到這一點:

.catch(e=>{
    if(e instanceof PageDoesNotExistError) {
        return new Page();
    }
    return Promise.reject(e);
})

把這三樣東西放在一起:

class Foo {
    changeName(path, newName) {
        return this.getPage(path)
            .then(page=> {
                // Some modifications are made to page, omitted here
                return page;
            })
            .catch(e=>{
                if(e instanceof PageDoesNotExistError) {
                    return new Page();
                }
                return Promise.reject(e);
            })
            .then(page=> {
                page.name = newName;
                return this.savePage(path, page);
            });
    }
}

您只需返回承諾,然后從任何嵌套的承諾中返回:

class Foo {
  changeName(path, newName) {
      return this.getPage(path)
        .catch(e => {
          if(e instanceof PageDoesNotExistError) {
            return new Page();
          }
        })
        .then(page=> {
          page.name = newName;

          return this.savePage(path, page); // assuming that this is a promise
        })
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM