promise 常见问题总结
promise 如何中断
promise 的缺点之一就是无法让 promise 中断
Promise.resolve().then(() => {console.log('then 1')
}).then(() => {console.log('then 2')
}).then(() => {console.log('then 3')
}).catch((err) => {console.log(err)
})
如上代码如何让 promise 的链式调用中断?
- 一种方法是在 then 1 中直接抛错, 这样就不会执行 then 2, then 3, 直接跳到 catch 方法打印 err(但此方法并没有实际中断)
Promise.resolve().then(() => {console.log('then 1')
throw new Error('xxx')
}).then(() => {console.log('then 2')
}).then(() => {console.log('then 3')
}).catch((err) => {console.log(err)
})
- 另一种方法就是在 then 1 中 return 一个新的 Promise, 但不改变其状态, 这样该 Promise 就一直处于 pedding 状态, 即不会执行后面任何方法
Promise.resolve().then(() => {console.log('then 1')
return new Promise(() => {})
}).then(() => {console.log('then 2')
}).then(() => {console.log('then 3')
}).catch((err) => {console.log(err)
})
- 中断有啥用? ———- 可以让我 想到 超时中断问题
假设我们要用 promsie 自己封装一个 ajax, 设置超时中断时间, 如果没返回就不用返回了, 返回也不做处理了, 不重要(虽然和上面的原理没关系, 但不重要, 上面是一个 promsie 的链式调用中断, 此例是实际应用中的问题, 你管我用几个 promsie 呢, 想到了记录一下)
function wrap(p1) {
let abort
let p2 = new Promise((resolve, reject) => {abort = reject})
let p = Promise.race([p1, p2])
// 将延时 promise 的 reject 方法挂在到 p1 与 p2 的 race 后的 promise 上, 可以在方法外通过调用 p 的 cancel 方法, 来触发 p2 的 reject
p.cancel = abort
return p
}
let fn = wrap(new Promise((resolve, reject) => {
// 假设 1 秒后 ajax 返回, 调用 resolve
setTimeout(() => {resolve()
}, 1000)
}))
fn.then(() => {console.log('ok')
}).catch(() => {console.log('err')
})
// 设置延时时间 500ms, 如果 500ms 数据买回来, 就中断
setTimeout(() => {fn.cancel()
}, 500)