ajax打開新窗口實現


最近開發中碰到一個問題,有一場景需要在ajax驗證通過后在新窗口打開一個url。 一開始通過在異步回調函數中使用window.open()來實現,但是發現這種實現方式會被瀏覽器攔截,需要用戶進行瀏覽器設置才能打開,但是這顯然不 適合在互聯網應用中對用戶做這個限制。因此就想有沒有什么辦法來解決?

辦法一:失敗

        首先的一個想法是js打開一個新窗口不行,有可能是瀏覽器對於js直接打開新窗口有安全限制,那么我form表單提交或者偽造一個url去觸發click 函數,總不應該會進行攔截了吧。試了之后遺憾地的發現:不行。查了一些資料,瀏覽器只有在認為click和submit在打開新窗口時(如果是_self 則不會有此限制),這些操作是由用戶主動觸發時才是安全可以被執行,而ajax回調函數中去執行click和submit被瀏覽器認為不是由用戶主動觸發 的,因此不能被安全執行,所以被攔截。

       代碼如下:試了之后,無奈的發現,不僅ajax回調中會被安全攔截,像timeout、interval這種也同樣會被瀏覽器認為不是由用戶主動觸發的操作,而被攔截,無奈失敗了!

$.ajax({
    url:url,
    data:form.serialize(),
    dataType: 'json'
}).done(function(o){
    if(o.success){
        if(o.data){
            $('#jump-url-div').val('http://www.XXX.com');
        }else{
                        _onFailure();
                }}else{_onFailure();}
}).fail(_onFailure);
setTimeout(function(){window.open($('#jump-url-div').val());},5000);

辦法二:失敗

  然后就想不在ajax異步回調中去要開新窗口,而是在ajax執行的函數中去延時去執行打開新窗口, 想到ajax是異步調用的,那么我在當前函數里通過while(true)來判斷url是否獲取完畢,如果取到url就去執行新窗口打開邏輯,這樣總該可以了吧,於是就寫了代碼:

 最后一執行,發現瀏覽器被掛住,且一直不打開新窗口。后來一查才知道,瀏覽器的 javascript執行引擎是單線程的,所謂的ajax異步執行,其實是在成功回調后,將當前的任務放到瀏覽器的javascript的執行隊列之中, 等待執行。而這里由於while(true)一直在執行,因此不可能去執行ajax的回調函數,因此url一直取不到,導致死循環,仍然失敗!

 

$.ajax({
    url:url,
    data:form.serialize(),
    dataType: 'json'
}).done(function(o){
    if(o.success){
        if(o.data){
            $('#jump-url-div').val('http://www.XXX.com');
        }else{
            _onFailure();
        }
    }else{
        _onFailure();
    }
}).fail(_onFailure);
while(true){
    if($('#jump-url-div').val()!=''){
        window.open($('#jump-url-div').val());
    break;
    }
}

 

 

辦法三:成功

后來一想,之所以瀏覽器認為打開新窗口不是由用戶主動發起的,是因為ajax的異步請求導致,而ajax不僅可以進行異步請求,也可以進行同步請求,然后就把這段代碼的ajax請求改為同步,調試通過,但是這種方法雖然解決了問題,但是也同樣失去了我們使用ajax的實衷,而且這種方法在jquery的使用手冊里也明確指出,其受到調用的接口的性能影響,如果長時間不響應,勢必會鎖住瀏覽器,失去異步響應的優勢。

如下:

 

$.ajax({
    url:url,
    data:form.serialize(),
    dataType: 'json',
    async:false
}).done(function(o){
    if(o.success){
        if(o.data){
            window.open('http://www.XXX.com');
        }else{
            newwin.close();
            $(document).trigger('simpleDialog',['#dialog-has-order']);
        }
    }else{
        _onFailure();
    }
}).fail(_onFailure);

 

 

 

 

 辦法四:成功

后來通過進一步查找,據說淘寶有一種作法,就是在ajax執行之前先打開一個新窗口,這時候是同步的,所以不會有問題,然后在異步調用成功后使用location.href將其指向新的url,如果失敗則將該窗口關閉,  但是這種方法帶來一個問題,就是當失敗后,會先打開一個窗口,然后再關閉,雖然一閃而過,但是對用戶總是一個困擾,相對來說還不如將ajax改成同步,畢竟現在的互聯網的訪問速度,不至於會將瀏覽器鎖住太長時間。

如下:

 

var newwindow=window.open("about:blank");
window.focus();
$.ajax({
    url:form.attr('action'),
    data:form.serialize(),
    dataType: 'json',
    async:false
}).done(function(o){
    if(o.success){
        if(o.data){
            newwindow.location.href="http://www.XXX.com";
                        newwindow.focus();
        }else{
            newwindow.close();
        }
    }else{
        newwindow.close();
    }
}).fail(function(){newwindow.close();});

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM