【发布时间】:2019-08-07 13:53:53
【问题描述】:
我想找到一个有两个承诺的解决方案。第一个承诺必须完成。第二个承诺不一定要完成,但用户不应该在重定向发生之前等待特定的时间。
我已尝试创建解决方案,但由于我是新手,不知道如何测试此代码或查看它是否有效。真的很想看看其他人对这段代码为什么好或坏的看法,并愿意改进。
async function apiPromise(url) {
try {
const response = await fetch(url);
const json = response.json();
return {json}
} catch (error) {
console.error(error);
}
}
// promise timeout wrapper race condition
function promiseTimeout(ms, promise) {
// Create a promise that rejects in <ms> milliseconds
let timeout = new Promise((resolve, reject) => {
let id = setTimeout(() => {
reject('Timed out in '+ ms + 'ms.')
}, ms)
})
// Returns a race between our timeout and the passed in promise
return Promise.race([
promise,
timeout
]).then(result => {
clearTimeout(id);
return result
})
}
// let's assume this runs, componentDidMount
function setup() {
let promises = [apiPromise('url'), timeoutPromise(5000, apiPromise('url'))]
Promise.all(promises)
.then(results => {
// do whatever with the results array
})
.catch(error=> {
console.error(error);
window.location.href= '/redirect'
})
}
apiPromise 函数用于尝试获取 URL。如果成功,它会解析,但随后 catch 语句会使用新的 Error 对象拒绝它
promiseTimeout 函数用于针对给定的承诺和超时创建竞争条件
setup 函数就像一个反应组件DidMount 或只是启动代码。
总而言之,我不确定是否:
1)我正确地写了apiPromise,并进行了适当的尝试和捕捉。这有意义吗?
2) 如果第二个承诺确实超时,我的 promise.all 是否会按预期工作,用户会被重定向?
【问题讨论】:
-
第一个函数中的经典错误 ... Promise 构造函数反模式 ... fetch 返回一个 Promise,不要将它包装在 Promise 中 ... 停止阅读
-
感谢您的输入,我将其更改为函数仅在函数中使用 try/catch 的位置,如果获取成功,则尝试返回带有数据的对象,如果失败控制台出错。问题:如果第二个 API 调用超时,那么我的设置函数中的捕获是否会起作用,然后用户被重定向?抱歉 - 我仍在学习并努力变得更好
-
Promise.all 要么全有,要么全无。一旦数组中的所有承诺都解决了,它就会解决,或者一旦其中一个被拒绝,它就会被拒绝。因此,如果您的第二个承诺失败,您将收到错误消息。所以catch块会被激活。
-
@Thuvarakan 我看过一些帖子解释如何让承诺进入挂起状态,然后看看它是否会履行或拒绝 - 然后他们抓住拒绝,然后按顺序将其返回给 Promise.all让它成功运行某些正确解决的承诺,而其他承诺被拒绝。根据您的经验,这行得通吗?如果您有多个请求,您是否只是将它们链接起来(即异步等待?)
-
@Yunjichu 是的,如果您在内部处理错误,那么 promise.all 将正常工作。但在您的情况下,promiseTimeout 函数正在返回拒绝。那么你需要在返回的promise中添加一个catch状态并在catch中解析promise。 promiseDemo.catch(error => null)
标签: javascript asynchronous promise race-condition