javascript - 我怎样才能消除这些嵌套的 promise ?

标签 javascript asynchronous ecmascript-6 promise es6-promise

我读到您应该在 JavaScript 中避免嵌套 promise ,因为它们往往是一种反模式,但我无法弄清楚如何在我的特定用例中避免它们。希望比我更有经验的人能看到我哪里出错了?任何建议将不胜感激!!

本质上,我正在异步检索一些数据,处理它并捕获可能的错误,然后异步保存一些数据。这是一个简化得多的示例:

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 的值解析的 promise (标有 //***** 的行*),以便我可以在其他地方做类似的事情:

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

最佳答案

How can I have changeName return a promise that will resolve with the value of this.savePage

返回 promise savePagethen 返回处理程序。这将解决 then 创建的 promise 来自 savePage 的 promise ,这意味着 then 创建的 promise 将根据 savePage 的 promise 实现或拒绝。做。 (如果您有兴趣,请在 my blog post here 中详细了解该术语。)

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

另外,您说过您希望调用者能够对 changePage 的返回值使用 promise 但你不会从 changePage 返回任何东西.您需要添加 return在整个结构面前,让你返回最终的 promise 。

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 e 来实现或 return 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);
            });
    }
}

关于javascript - 我怎样才能消除这些嵌套的 promise ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42750719/

相关文章:

javascript - 尝试导入错误 : 'BrowseRouter' is not exported from 'react-router-dom' (imported as 'Router' )

java - 有什么方法可以自动创建 Mongo 编解码器吗?

javascript - 在评估 Promise.all 的结果时使用没有超时值的 setTimeout

javascript - ES6中使用Array类方法进行HTMLCollection DOM遍历

JavaScript AppendChild 在数组上创建元素

javascript - FireFox 中的自定义元素非法构造函数

javascript - 语法错误: <a> link not working by clicking,只能通过右键+ "open link in new tab"命令打开

javascript - 使用 jQuery 封装动态内容

javascript - 以特定的时间间隔连续调用ajax函数直到满足条件?

javascript - preact 异步路由器找不到 block