CDHtmlDialog探索----WebBrowser扩展和网页Javascript错误处理

当WebBrowser控件(CDHtmlDialog自动创建了WebBrowser控件)加载的网页中含有错误Javascript代码时默认情况下控件会弹出错误信息提示对话框,相对于用户体验来说这样的提示完全不是开发人员想要的,针对这个问题有两个解决方案,一是完全屏蔽掉错误提示,二是控制错误的提示并且记录错误信息同时也可以控制出现错误后Javascript是否继续执行。

1、屏蔽错误信息提示


1

m_pBrowserApp->put_Silent(VARIANT_TRUE);

在CDHtmlDialog::OnInitDialog()的代码中首先了创建WebBrowser控件,然后把控件的Browser对象赋值给m_pBrowserApp(这是CDHtmlDialog完成的不需要自己处理)。WebBrowser的put_Silent函数在官方给出的说明是禁用所有的对话框,但例外情况是它不会影响SSL安全认证需要的进示对话框。绝大多数情况下这就可以解决问题了,记得很久以前我遇到过一种情况就是虽然调用了put_Silent但是还是有极个别的js错误是无法屏蔽掉的依然会显示出来(在网页含有嵌套页面时会错误无法屏蔽,不知道是否还有其它情况),现在找不到这样的网页了,如果谁遇到这种情况了建议给我发上个URL让我也重温一下当年阳光灿烂的时刻。

2、控制错误提示并进行记录

  这要比第一种方法复杂上许多,简短的来说就是自定义COleControlSite类并实现IOleCommandTarget接口,IOleCommandTarget接口是错误控制的关健,错误发生时会触发此接口的Exec函数并为nCmdID参数赋值为OLECMDID_SHOWSCRIPTERROR,这样就可以得到错误信息了。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

IOleCommandTarget : public IUnknown

    {

    public:

        virtual /* [input_sync] */ HRESULT STDMETHODCALLTYPE QueryStatus(

            /* [unique][in] */ __RPC__in_opt const GUID *pguidCmdGroup,

            /* [in] */ ULONG cCmds,

            /* [out][in][size_is] */ __RPC__inout_ecount_full(cCmds) OLECMD prgCmds[  ],

            /* [unique][out][in] */ __RPC__inout_opt OLECMDTEXT *pCmdText) = 0;

        

        virtual HRESULT STDMETHODCALLTYPE Exec(

            /* [unique][in] */ __RPC__in_opt const GUID *pguidCmdGroup,

            /* [in] */ DWORD nCmdID,

            /* [in] */ DWORD nCmdexecopt,

            /* [unique][in] */ __RPC__in_opt VARIANT *pvaIn,

            /* [unique][out][in] */ __RPC__inout_opt VARIANT *pvaOut) = 0;

        

    };

   

现在我们开始实现自定义的COleControlSite


1

2

3

4

5

6

7

8

9

10

11

12

13

class CMyControlSite : public COleControlSite

public

    CMyControlSite(COleControlContainer *pCntr):COleControlSite(pCntr) {}

protected

    DECLARE_INTERFACE_MAP() 

    BEGIN_INTERFACE_PART(OleCommandTarget, IOleCommandTarget) 

        STDMETHOD(QueryStatus)(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText); 

        STDMETHOD(Exec)(const GUID* pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG* pvaIn, VARIANTARG* pvaOut); 

    END_INTERFACE_PART(OleCommandTarget) 


1

MFC提供了很多宏用于简化COM相关功能的开发,对COM接口的实现方式在MFC中具体体现方式是内嵌类,背后的设计思想是COM聚合,每个接口都产生一个内嵌类,所有的接口都聚合到外层的类。DECLARE_INTERFACE_MAP()  实际上就是定义一个数组以及查询操作,BEGIN_INTERFACE_PART定义一个命名为XOleCommandTarget的内嵌类(内嵌类的命名规则是XName)并定义IUnknown接口的三个方法AddRef、Release、QueryInterface。END_INTERFACE_PART定义一个m_xOleCommandTarget的成员类型为XOleCommandTarget(定义的成员命名规则就是m_xName),并把XOleCommandTarget类声明为外层类的友元类在示例中外层类指CMyControlSite。

STDMETHOD宏定义为virtual __declspec(nothrow) HRESULT __stdcall,该宏定义函数为虚函数返回值为HRESULT,函数调用约定为__stdcall,并且在此函数上禁止异常。__declspec(nothrow)用定告诉编译器它修饰的函数以及此函数调用的函数不会产生C++异常调用从可以优化代码性能和代码尺寸(默认情况下C++编译器为了进行异常处理会在拥有throw调用的函数中自动生成相关的异常处理代码)。通常情况下HRESULT返回值就表达了错误信息,HRESULT是个32位值,不同的位域用于不同的目的,也可以使用自定义的位域,具体的信息可以参考http://en.wikipedia.org/wiki/HRESULT。由于COM本身的语言中立性所以不应该在COM组件对外公布的信息中掺杂特定语言相关的特性。如果需要提供更详尽的错误信息那么应该实现COM的IErrorInfo接口。言归正传以下是CMyControlSite的类实现代码

BEGIN_INTERFACE_MAP(CMyControlSite, COleControlSite)   INTERFACE_PART(CMyControlSite, IID_IOleCommandTarget, OleCommandTarget)


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

<em id="__mceDel"><em id="__mceDel">END_INTERFACE_MAP() 

HRESULT CMyControlSite::XOleCommandTarget::Exec 

(const GUID* pguidCmdGroup, DWORD nCmdID, 

 DWORD nCmdexecopt, VARIANTARG* pvaIn, VARIANTARG* pvaOut ) 

    HRESULT hr = OLECMDERR_E_NOTSUPPORTED; 

    //return S_OK; 

    if (pguidCmdGroup && IsEqualGUID(*pguidCmdGroup, CGID_DocHostCommandHandler)) 

    

        switch (nCmdID)  

        

        case OLECMDID_SHOWSCRIPTERROR: 

            

                IHTMLDocument2*             pDoc = NULL; 

                IHTMLWindow2*               pWindow = NULL; 

                IHTMLEventObj*              pEventObj = NULL; 

                BSTR                        rgwszNames[5] =  

                {  

                    <span>SysAllocString(L"errorLine"), </span><br><span>SysAllocString(L"errorCharacter"), </span><br><span>SysAllocString(L"errorCode"), </span><br><span>SysAllocString(L"errorMessage"), </span><br><span>SysAllocString(L"errorUrl")</span>

                }; 

                DISPID                      rgDispIDs[5]; 

                VARIANT                     rgvaEventInfo[5]; 

                DISPPARAMS                  params; 

                BOOL                        fContinueRunningScripts = true

                params.cArgs = 0; 

                params.cNamedArgs = 0; 

                

                hr = pvaIn->punkVal->QueryInterface(IID_IHTMLDocument2, (void **) &pDoc);     

                 

                hr = pDoc->get_parentWindow(&pWindow); 

                pDoc->Release(); 

                

                hr = pWindow->get_event(&pEventObj); 

                

                for (int i = 0; i < 5; i++)  

                {   

                    

                    hr = pEventObj->GetIDsOfNames(IID_NULL, &rgwszNames[i], 1,  

                        LOCALE_SYSTEM_DEFAULT, &rgDispIDs[i]); 

                

                    hr = pEventObj->Invoke(rgDispIDs[i], IID_NULL, 

                        LOCALE_SYSTEM_DEFAULT, 

                        DISPATCH_PROPERTYGET, ¶ms, &rgvaEventInfo[i], 

                        NULL, NULL); 

                    //可以在此记录错误信息</em></em>


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

                    //必须使用SysFreeString来释放SysAllocString分配的内存,SysAllocString在分配的内存中记录了字符的长度

                    SysFreeString(rgwszNames[i]); 

                

                // At this point, you would normally alert the user with  

                // the information about the error, which is now contained 

                // in rgvaEventInfo[]. Or, you could just exit silently. 

                (*pvaOut).vt = VT_BOOL; 

                if (fContinueRunningScripts) 

                

                    // 在页面中继续执行脚本

                    (*pvaOut).boolVal = VARIANT_TRUE; 

                

                else

                

                    // 停止在页面中执行脚本 

                    (*pvaOut).boolVal = VARIANT_FALSE;    

                }  

                break

            

        default

            hr =OLECMDERR_E_NOTSUPPORTED;

            break

        

    

    else

    

        hr = OLECMDERR_E_UNKNOWNGROUP;

    

    return (hr); 

ULONG FAR EXPORT CMyControlSite::XOleCommandTarget::AddRef()  

{  

    METHOD_PROLOGUE(CMyControlSite, OleCommandTarget)  

        return pThis->ExternalAddRef();  

}  

ULONG FAR EXPORT CMyControlSite::XOleCommandTarget::Release()  

{  

    METHOD_PROLOGUE(CMyControlSite, OleCommandTarget)  

        return pThis->ExternalRelease();  

}  

HRESULT FAR EXPORT CMyControlSite::XOleCommandTarget::QueryInterface(REFIID riid, void **ppvObj)  

{  

    METHOD_PROLOGUE(CMyControlSite, OleCommandTarget)  

        HRESULT hr = (HRESULT)pThis->ExternalQueryInterface(&riid, ppvObj);  

    return hr;  

STDMETHODIMP CMyControlSite::XOleCommandTarget::QueryStatus(  

    /* [unique][in] */ const GUID __RPC_FAR *pguidCmdGroup,  

    /* [in] */ ULONG cCmds,  

    /* [out][in][size_is] */ OLECMD __RPC_FAR prgCmds[ ],  

    /* [unique][out][in] */ OLECMDTEXT __RPC_FAR *pCmdText  

    )  

{  

    METHOD_PROLOGUE(CMyControlSite, OleCommandTarget)  

        return OLECMDERR_E_NOTSUPPORTED;  

}  

实现CMyControlSite后需要应用到CDHtmlDialog上,重写CreateControlSite虚函数既可


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

virtual BOOL CreateControlSite(COleControlContainer* pContainer,

        COleControlSite** ppSite, UINT  nID , REFCLSID  clsid )

{

        if(ppSite == NULL)

    {

        ASSERT(FALSE);

        return FALSE;

    }

    CMyControlSite *pBrowserSite =

        new CMyControlSite (pContainer, this);

    if (!pBrowserSite)

        return FALSE;

    *ppSite = pBrowserSite;

    return TRUE;

}

现在就可以去编译测试了。到目前还有一个问题没有考虑,如果这段代码整合到现有的CDHtmlDialog应用中而现有的代码使用了其它默认的设定比如说自定义WebBrowser的右健菜单或使用了GetIDispatch函数等情况下原有的代码就不能正常工作了。这部分功能是在MFC的CBrowserControlSite类中处理的,所以CMyControlSite应该把CBrowserControlSite的功能也实现一遍以使CDHtmlDialog的原有封装性不被破坏。在CMyControlSite中实现IDocHostUIHandler接口既可完成此功能。代码声明如下


1

public:


1

CMyControlSite(COleControlContainer *pCnt, CDHtmlDialog *pHandler):COleControlSite(pCnt),m_pHandler(pHandler) {}


1

protected:


1

CDHtmlDialog *m_pHandler;


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

BEGIN_INTERFACE_PART(DocHostUIHandler, IDocHostUIHandler)

        STDMETHOD(ShowContextMenu)(DWORD, LPPOINT, LPUNKNOWN, LPDISPATCH);

        STDMETHOD(GetHostInfo)(DOCHOSTUIINFO*);

        STDMETHOD(ShowUI)(DWORD, LPOLEINPLACEACTIVEOBJECT,

            LPOLECOMMANDTARGET, LPOLEINPLACEFRAME, LPOLEINPLACEUIWINDOW);

        STDMETHOD(HideUI)(void);

        STDMETHOD(UpdateUI)(void);

        STDMETHOD(EnableModeless)(BOOL);

        STDMETHOD(OnDocWindowActivate)(BOOL);

        STDMETHOD(OnFrameWindowActivate)(BOOL);

        STDMETHOD(ResizeBorder)(LPCRECT, LPOLEINPLACEUIWINDOW, BOOL);

        STDMETHOD(TranslateAccelerator)(LPMSG, const GUID*, DWORD);

        STDMETHOD(GetOptionKeyPath)(OLECHAR **, DWORD);

        STDMETHOD(GetDropTarget)(LPDROPTARGET, LPDROPTARGET*);

        STDMETHOD(GetExternal)(LPDISPATCH*);

        STDMETHOD(TranslateUrl)(DWORD, OLECHAR*, OLECHAR **);

        STDMETHOD(FilterDataObject)(LPDATAOBJECT , LPDATAOBJECT*);

    END_INTERFACE_PART(DocHostUIHandler)

以下是实现代码


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

BEGIN_INTERFACE_MAP(CMyControlSite, COleControlSite) 

    INTERFACE_PART(CMyControlSite, IID_IDocHostUIHandler, DocHostUIHandler)

    INTERFACE_PART(CMyControlSite, IID_IOleCommandTarget, OleCommandTarget)

END_INTERFACE_MAP() 

STDMETHODIMP CMyControlSite::XDocHostUIHandler::GetExternal(LPDISPATCH *lppDispatch)

{

    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)

    return pThis->m_pHandler->GetExternal(lppDispatch);

}

STDMETHODIMP CMyControlSite::XDocHostUIHandler::ShowContextMenu(

    DWORD dwID, LPPOINT ppt, LPUNKNOWN pcmdTarget, LPDISPATCH pdispReserved)

{

    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)

    return pThis->m_pHandler->ShowContextMenu(dwID, ppt, pcmdTarget, pdispReserved);

}

STDMETHODIMP CMyControlSite::XDocHostUIHandler::GetHostInfo(

    DOCHOSTUIINFO *pInfo)

{

    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)

    return pThis->m_pHandler->GetHostInfo(pInfo);

}

STDMETHODIMP CMyControlSite::XDocHostUIHandler::ShowUI(

    DWORD dwID, LPOLEINPLACEACTIVEOBJECT pActiveObject,

    LPOLECOMMANDTARGET pCommandTarget, LPOLEINPLACEFRAME pFrame,

    LPOLEINPLACEUIWINDOW pDoc)

{

    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)

    return pThis->m_pHandler->ShowUI(dwID, pActiveObject, pCommandTarget, pFrame, pDoc);

}

STDMETHODIMP CMyControlSite::XDocHostUIHandler::HideUI(void)

{

    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)

    return pThis->m_pHandler->HideUI();

}

STDMETHODIMP CMyControlSite::XDocHostUIHandler::UpdateUI(void)

{

    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)

    return pThis->m_pHandler->UpdateUI();

}

STDMETHODIMP CMyControlSite::XDocHostUIHandler::EnableModeless(BOOL fEnable)

{

    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)

    return pThis->m_pHandler->EnableModeless(fEnable);

}

STDMETHODIMP CMyControlSite::XDocHostUIHandler::OnDocWindowActivate(BOOL fActivate)

{

    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)

    return pThis->m_pHandler->OnDocWindowActivate(fActivate);

}

STDMETHODIMP CMyControlSite::XDocHostUIHandler::OnFrameWindowActivate(

    BOOL fActivate)

{

    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)

    return pThis->m_pHandler->OnFrameWindowActivate(fActivate);

}

STDMETHODIMP CMyControlSite::XDocHostUIHandler::ResizeBorder(

    LPCRECT prcBorder, LPOLEINPLACEUIWINDOW pUIWindow, BOOL fFrameWindow)

{

    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)

    return pThis->m_pHandler->ResizeBorder(prcBorder, pUIWindow, fFrameWindow);

}

STDMETHODIMP CMyControlSite::XDocHostUIHandler::TranslateAccelerator(

    LPMSG lpMsg, const GUID* pguidCmdGroup, DWORD nCmdID)

{

    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)

    return pThis->m_pHandler->TranslateAccelerator(lpMsg, pguidCmdGroup, nCmdID);

}

STDMETHODIMP CMyControlSite::XDocHostUIHandler::GetOptionKeyPath(

    LPOLESTR* pchKey, DWORD dwReserved)

{

    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)

    return pThis->m_pHandler->GetOptionKeyPath(pchKey, dwReserved);

}

STDMETHODIMP CMyControlSite::XDocHostUIHandler::GetDropTarget(

    LPDROPTARGET pDropTarget, LPDROPTARGET* ppDropTarget)

{

    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)

    return pThis->m_pHandler->GetDropTarget(pDropTarget, ppDropTarget);

}

STDMETHODIMP CMyControlSite::XDocHostUIHandler::TranslateUrl(

    DWORD dwTranslate, OLECHAR* pchURLIn, OLECHAR** ppchURLOut)

{

    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)

    return pThis->m_pHandler->TranslateUrl(dwTranslate, pchURLIn, ppchURLOut);

}

STDMETHODIMP CMyControlSite::XDocHostUIHandler::FilterDataObject(

    LPDATAOBJECT pDataObject, LPDATAOBJECT* ppDataObject)

{

    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)

    return pThis->m_pHandler->FilterDataObject(pDataObject, ppDataObject);

}

STDMETHODIMP_(ULONG) CMyControlSite::XDocHostUIHandler::AddRef()

{

    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)

        return pThis->ExternalAddRef();

}

STDMETHODIMP_(ULONG) CMyControlSite::XDocHostUIHandler::Release()

{

    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)

        return pThis->ExternalRelease();

}

STDMETHODIMP CMyControlSite::XDocHostUIHandler::QueryInterface(

    REFIID iid, LPVOID far* ppvObj)    

{

    METHOD_PROLOGUE_EX_(CMyControlSite, DocHostUIHandler)

        return pThis->ExternalQueryInterface(&iid, ppvObj);

}

STDMETHODIMP宏的定义是HRESULT __stdcall,STDMETHODIMP_宏指定了返回值,这两个宏用在cpp实现文件中,对应用于声明时使用的STDMETHOD和STDMETHOD_。

METHOD_PROLOGUE_EX_宏定义了pThis指针来指向外层类。

以上代码基于VS2008,由于不同版本的VS所带的MFC库版本不尽一致所以需要根本具体的版本来处理,目前已知的不同部分主要集中在CreateControlSite上。

时间: 2024-08-12 22:35:33

CDHtmlDialog探索----WebBrowser扩展和网页Javascript错误处理的相关文章

JavaScript错误/异常处理

JavaScript Try...Catch 语句 介绍:JavaScript中的try...carch语句的作用和C#中的try...catch语句的作用一样, 都是捕获并处理异常. 语法: try { //在此运行代码 } catch(err) { //在此处理错误 } 例子: <html> <head> <script type="text/javascript"> var txt="" function message()

webBrowser中操作网页元素全攻略

webBrowser中操作网页元素全攻略 2012-12-20 14:21 188人阅读 评论(0) 收藏 举报 1.获取非input控件的值: webBrowser1.Document.All["控件ID"].InnerText; 或webBrowser1.Document.GetElementById("控件ID").InnerText; 或webBrowser1.Document.GetElementById("控件ID").GetAttr

Java抓取网页数据(原网页+Javascript返回数据)

转载请注明出处! 原文链接:http://blog.csdn.net/zgyulongfei/article/details/7909006 有时候因为种种原因,我们须要採集某个站点的数据,但因为不同站点对数据的显示方式略有不同! 本文就用Java给大家演示怎样抓取站点的数据:(1)抓取原网页数据:(2)抓取网页Javascript返回的数据. 一.抓取原网页. 这个样例我们准备从http://ip.chinaz.com上抓取ip查询的结果: 第一步:打开这个网页,然后输入IP:111.142.

Ext JS学习第十天 Ext基础之 扩展原生的javascript对象(二)

此文来记录学习笔记: 今天继续说Ext.Array,Ext.Function,Ext.Date,Ext.Error ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Ext.Ar

C# WebBrowser准确判断网页最终装载完毕

== 最近写了个软件叫WebAutoScript,目的用于,网页的自动操作处理,就是说,所有你在网页上面的操作,都可以录到一个脚本中,然后可以回放这个操作过程..我是说任何过程. 程序是用C#写的,其中遇到了一个难题,对于网页,我是用C#内置的WebBrowser控件控制,但是这个控件有个问题,就是不能准确判断网页什么时候最终装载完毕,如果这个不能判断的话,我根本不可以判断什么时候执行下一个动作,因为网页还没有打开,不可能去点击还没有出现的按钮等...google了海内外,竟然没有人搞定过,除非

第一百二十三节,JavaScript错误处理与调试

JavaScript错误处理与调试 学习要点: 1.浏览器错误报告 2.错误处理 3.错误事件 4.错误处理策略 5.调试技术 6.调试工具 JavaScript在错误处理调试上一直是它的软肋,如果脚本出错,给出的提示经常也让人摸不着头脑.ECMAScript第3版为了解决这个问题引入了try...catch和throw语句以及一些错误类型,让开发人员更加适时的处理错误. 一.浏览器错误报告 随着浏览器的不断升级,JavaScript代码的调试能力也逐渐变强.IE.Firefox.Safari.

javascript错误:对象不支持此属性或方法

javascript错误:对象不支持此属性或方法 出现如上错误的原因主要有以下两种: 1.方法对应的JS函数未定义 2.属性所用的id名字跟函数名相同也会报此错误,id或函数名改个地方即可.

JavaScript之基础-12 JavaScript 错误处理

一.JavaScript 错误处理 错误处理概述 - 错误,指程序中的非正常运行状态,在其它编程语言中称为"异常"或"错误".解释器会为每个错误情形创建并抛出一个Error对象,其中包含错误的描述信息 - ECMAScript定义了六种类型的错误(EvalError,RangeError,REferenceError,SyntaxError,TypeError,URIError).除此之外,还可以使用Error构造方法创建自定义的Error对象,并使用throw语句

JavaScript错误处理

JavaScript 错误 - Throw.Try 和 Catch JavaScript 测试和捕捉 try 语句允许我们定义在执行时进行错误测试的代码块. catch 语句允许我们定义当 try 代码块发生错误时,所执行的代码块. JavaScript 语句 try 和 catch 是成对出现的. 语法 try { //在这里运行代码 } catch(err) { //在这里处理错误 } 实例 在下面的例子中,我们故意在 try 块的代码中写了一个错字. catch 块会捕捉到 try 块中的