js 怎么避免重复的异步操作(不问了,目前没办法后台做到,只能改造前端了)

let x=0;

function add() {
    return new Promise(resolve => {
        if (x===1) return resolve(x);

        //这里是一个异步操作
        setTimeout(()=>resolve(x+=1),1000);
    })
}

add().then(r=>console.log(r));
add().then(r=>console.log(r));
add().then(r=>console.log(r));

我要怎么样保证add()在x===1时不会进行异步操作?而且我不知道会有多少个add()。

具体场景是:
用户进入一个页面时,会触发多个ajax,这些ajax的后台方法里都要调一次add()去验证一下权限(验证权限是个异步操作,即setTimeout),如果验证过了(即X===1),那就不用验证直接放行,否则拦截这个请求。

阅读 4.4k
7 个回答

我看了你的需求,为什么不考虑在页面加载的第一个请求,先发add请求验证是否有权限,有权限的话再发,其他的请求,这是个同步关系的请求,或者使用token或session。

不知道具体需求到底是什么哈,但是promise是eager的,一旦初始化就没法「不进行」了,但是你可以在 x===1 的时候 reject:

function add() {

return new Promise((resolve, reject) => {
    if (x===1) reject(x);

    //这里是一个异步操作
    setTimeout(()=>resolve(x+=1),1000);
})

}

----- 修改 -----

如果是想要完全阻止后面操作的话,那就不要一次性开始三个 promise 了呀:

add().then(r => {
    console.log(r)
    return add()
}).then(r => {
    console.log(r)
    return add()
})

写成 await 一样的

看你的代码是没问题的,因为你的add()里面需要1000ms之后,才能将x变为1;但是你的三个add()是同时开始执行的,这三个执行的时候,x都还没变成1,所以,均执行到了setTimeout部分!

这段代码,就执行1次,因为后面的add()是在第1个add()执行有结果之后,才开始执行的。

add().then(r=>console.log(r));
setTimeout(() => {
    add().then(r=>console.log(r));
    add().then(r=>console.log(r));
}, 2000)

你是想:在一个add执行的过程中,其他的add都需要等待吗?

你这是写在node里的吧?

身份认证一定是异步动作,而且确实每个接口都需要进行验证。
所以,也就没有什么是否已经验证过的问题。

在接收到请求的第一步,就是鉴权(当然前面还有路由分发)。鉴权完毕后再进入主程序。
所以这是唯一入口,不存在多次的问题。

具体场景是:
用户进入一个页面时,会触发多个ajax,这些ajax的后台方法里都要调一次add()去验证一下权限(验证权限是个异步操作,即setTimeout),如果验证过了(即X===1),那就不用验证直接放行,否则拦截这个请求。

Promise在执行后会保存自己的状态,一个Promize多次then并不会重复执行其内的代码。

进入一个页面时:

let isAuthorized = new Promise((resolve, reject)=> ajax.get("/isAuthorized")).then(d=>d.IsAuthorized ? resolve() : reject());

让多个ajax都依赖于这个Promise的结果:

/*ajax 1*/ isAuthorized.then(d=>/*is authorized*/doYourThings1()).catch(ex=>/*not authorized*/showUnauthorizedMessage);
/*ajax 2*/ isAuthorized.then(d=>/*is authorized*/doYourThings2()).catch(ex=>/*not authorized*/showUnauthorizedMessage);

我大概理解需求为:初始N个请求,每次进行一个请求前要先调用一个验证方法,有权限才能进行,否则中断。
(如果理解错误请留言再一起讨论)
两个方案:
1.不推荐每次请求前都进行权限校验,条件允许的话改为在http-cookie或http-header等中使用token,可以自行百度“前端鉴权”,方法很多。

2.无法使用token,在现有方法中修改
思路:异步是个大问题,所以校验方法可以搞个同步,N个请求需要挨个执行,使用promise


    function add(callback) {
        // 鉴权请求
        $.ajax({
            url: url,
            async: false, // 同步
            data: data,
            success: function (res) {
                if (res === 1) {
                    callback()
                } else {
                    console.log('error')
                    throw 'throw error1'; // 无权限时捕获err中断请求
                }
            }
        })
    }

    // 开始载入请求 
    function a() { console.log('a') }
    function b() { console.log('b') }
    function c() { console.log('c') }
    function d() { console.log('d') }


    Promise.resolve()
        .then(add(a))
        .then(add(b))
        .then(add(c))
        .then(add(d))
        .catch(err => { console.log('errrrrrrrr') })
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题