我已经习惯了 promise 链接数组。当每个 promise 都是一行长时,读取 promise 链非常容易,例如
myArray.map(x => convertX)
.filter()
.whatever()
.etc()
这非常容易阅读。然而,当我使用自定义函数创建 promise 链时,它会变得更加困惑。
database.query(first query)
.then(results => {
// do stuff
// do more
// even more
return database.query(second query)
})
.then(results => {
// rinse and repeat
})
.catch(err => {
// error handling
})
现在,这可能是清晰的,但是当 promise 链进一步延伸时,它就会变得有点多。如果我让每个 promise 都有自己的功能,那么我可以简化流程,使代码看起来像这样(在我看来,可读性提高了 1000 倍)。
db.query(first query)
.then(storeFirstQuery)
.then(secondQueryAndStoreIt)
.then(thirdQueryAndStoreIt)
.catch(errHandlingFunction)
这样,我就可以重新排列函数,而不必操作从一个 promise 传递到下一个 promise 的值。如果一个 Promise 使用另一个 Promise 的结果,它只需要在另一个 Promise 之后,但不必紧跟在另一个 Promise 之后。这样我就可以在任何需要的地方偷偷 promise 。
但是,这要求我的 promise 链使用每个 promise 范围之外的变量。有没有经过验证的正确方法可以做到这一点?
编辑 - 似乎 async
/await
是执行此操作的最佳方法,但我在 Heroku 上运行 Node,但尚不支持它:/
最佳答案
好吧,你可以使用类似的 promise :
myArray.map(x => convertX)
.filter()
.whatever()
.etc()
如果你使用我的rsp来自 npm 的模块。
除此之外,您还可以使用 ES2017 的 async
/await
功能来简化 Promise 链,尤其是它们的范围。
因为使用这样的代码:
db.query(first query)
.then(storeFirstQuery)
.then(secondQueryAndStoreIt)
.then(thirdQueryAndStoreIt)
.catch(errHandlingFunction)
如果您需要在最后一个 thirdQueryAndStoreIt()
处理程序中使用第一个查询的结果,则在访问超出范围的数据时会遇到问题。但是当你这样做时:
try {
let a = await db.query(first query);
let b = await storeFirstQuery();
let c = await secondQueryAndStoreIt();
let d = await thirdQueryAndStoreIt(a); // use 'a' here
} catch (e) {
errHandlingFunction(e);
}
那么您就不会遇到范围问题,因为您可以轻松访问所有先前分配的变量。
查看支持此语法的 Node 版本:
您可以将其与开箱即用的 Node v7.6+ 或带有 --harmony
标志的 Node v7.0+ 一起使用。
对于较旧的 Node 版本,您可以使用 co或Bluebird.coroutine对于使用生成器函数和 yield
而不是 await
的类似语法。
关于javascript - 保持 Promise 链的可读性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42765589/