乐趣区

promise常见问题总结

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)
退出移动版