延迟表单提交,ajax,&弹出窗口阻止程序

时间:2016-08-03 23:47:24

标签: javascript ajax forms

我的网站上有一个简单的注册表单,用户可以在其中输入电子邮件和姓名。

为了避免出现双重注册错误,我有一个简单的Ajax调用来查看电子邮件是否已经存在。如果是这样,我什么也不做,如果没有,我提交表格。

我的问题是表单的目标是extension ViewController: AVCaptureFileOutputRecordingDelegate { func capture(_ captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAt outputFileURL: URL!, fromConnections connections: [Any]!, error: Error!) { guard let data = NSData(contentsOf: outputFileURL as URL) else { return } print("File size before compression: \(Double(data.length / 1048576)) mb") let compressedURL = NSURL.fileURL(withPath: NSTemporaryDirectory() + NSUUID().uuidString + ".m4v") compressVideo(inputURL: outputFileURL as URL, outputURL: compressedURL) { (exportSession) in guard let session = exportSession else { return } switch session.status { case .unknown: break case .waiting: break case .exporting: break case .completed: guard let compressedData = NSData(contentsOf: compressedURL) else { return } print("File size after compression: \(Double(compressedData.length / 1048576)) mb") case .failed: break case .cancelled: break } } } func compressVideo(inputURL: URL, outputURL: URL, handler:@escaping (_ exportSession: AVAssetExportSession?)-> Void) { let urlAsset = AVURLAsset(url: inputURL, options: nil) guard let exportSession = AVAssetExportSession(asset: urlAsset, presetName: AVAssetExportPresetMediumQuality) else { handler(nil) return } exportSession.outputURL = outputURL exportSession.outputFileType = AVFileTypeQuickTimeMovie exportSession.shouldOptimizeForNetworkUse = true exportSession.exportAsynchronously { () -> Void in handler(exportSession) } } } ,因此延迟的提交调用会触发浏览器上的弹出窗口阻止程序。

现在,我知道为什么这种情况发生了 - 我不再是受信任的点击事件了。我将Ajax调用更改为同步,但我收到一条警告,即不推荐在主线程上同步Ajax调用。

所以我目前的选择似乎是:

  • 无论如何都要使用同步Ajax调用,但最终它会停止工作
  • 删除表单上的目标_blank,以便重定向到同一页面(糟糕的用户体验)
  • ???

有没有更好的方法来解决弹出窗口阻止程序,看到我的延迟表单提交为弹出窗口?

代码:

HTML:

_blank

JS:

<form action="//external-site.com" method="post" target="_blank" onsubmit="onSubmitSignupForm(event)">
    ...
</form>

1 个答案:

答案 0 :(得分:0)

好的,所以我有一个解决方案,虽然它可能对我的情况有点具体,并且如果用户已经注册,我会重定向用户。

我基本上在最初提交表单时打开一个新的中间页面(因此在可信任事件中解决弹出问题)并在该页面上填充隐藏表单(如果用户需要,可以手动提交链接)。发送ajax电话,根据结果,我要么在第2页提交表单,要么在他们已经注册时重定向。

  1. 用户在Page1上提交表单
  2. 停止事件,并打开Page2,它具有相同的形式,尽管是隐藏的
  3. 使用Page1
  4. 上表单中的值填充Page2上的表单
  5. 在Page2上显示一条消息,说我们正在处理它,以及手动提交隐藏表单的链接(良好的用户体验)
  6. 在Page1上,触发Ajax请求以查看用户是否已订阅
  7. 当Ajax结果出现时,可能会发生两件事
  8. (a)用户未注册 - 提交Page2上的表单(可以选择将Page1重定向到内容)
  9. (b)用户已注册 - 将第2页重定向到内容
  10. 唯一需要注意的事项是确保在填写表单之前完全加载Page2并返回Ajax结果。为此,我使用一个带有onload事件的简单布尔系统。

    代码看起来像这样:

    function onSubmitSignupForm( e )
    {
        e.preventDefault();
        var $form   = e.target;
    
        var name = ...; // get name value from form
        var email = ...; // get email value from form
    
        // open a new window that we'll be able to control and redirect in (otherwise, we'll
        // get stung with a trying to open a popup, as when we get the result, we'll no longer
        // be in the trusted click event)
        var win = window.open( '/signup/', '_blank' );
        win.onload = function() {
            win.setDetails( name, email ); // fill in the hidden form
        }
    
        // check if the email is already signed up
        // NOTE: result might be null if we couldn't reach the server
        checkEmail( name, email, function onFinish( result ){
    
            // set the result in the other window
            // NOTE: the window might not have loaded yet
            if( typeof win.setResult == 'undefined' )
            {
                var f       = win.onload; // replace the one we already have
                win.onload  = function(){
                    if( f )
                        f();
                    win.setResult( result );
                }
            }
            else
                win.setResult( result );
        });
    }
    

    setDetailssetResult都会尝试调用第三个函数handleResult,它只会继续由两个函数设置的布尔值为真。