JavaScript?Promise執(zhí)行流程深刻理解
手撕Promise
手寫一個(gè)Promise已經(jīng)是一個(gè)常見(jiàn)的手寫功能了,雖然實(shí)際工作上可能并不會(huì)用到。但是在面試時(shí)還是會(huì)經(jīng)常被提起的。
看完收獲
- 實(shí)現(xiàn)一個(gè)手寫promise
- 對(duì)promise執(zhí)行流程有著更深刻的理解
- 從底層理解proimse,應(yīng)對(duì)各種面試題
Promise分析
作用
通過(guò)鏈?zhǔn)秸{(diào)用的方式,解決回調(diào)地獄的問(wèn)題。
特點(diǎn)
是ES6中新增的引用類型,通過(guò)new關(guān)鍵詞來(lái)創(chuàng)建實(shí)例。
存在3個(gè)狀態(tài):
- pending
- fulfilled
- rejected
且狀態(tài)變成fulfilled或者rejected后不可再次變更,具有不可逆性。
new Promise創(chuàng)建實(shí)例的時(shí)候必須要傳入一個(gè)函數(shù),且這個(gè)函數(shù)會(huì)有2個(gè)參數(shù)resolve
和reject
深入學(xué)習(xí)JavaScript中的promise
總體實(shí)現(xiàn)
首先我們可以按照Promise的特點(diǎn)來(lái)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的總體結(jié)構(gòu)。
- 他是一個(gè)構(gòu)造函數(shù),每個(gè)創(chuàng)建的promise都有各自狀態(tài)和值,且狀態(tài)初始值為pending,值為undefined。
- 創(chuàng)建實(shí)例的時(shí)候需要傳入一個(gè)函數(shù),而這個(gè)函數(shù)可以接受2個(gè)函數(shù)作為參數(shù),這2個(gè)函數(shù)都有一個(gè)參數(shù),且都可以更改實(shí)例的狀態(tài)和值。
- 根據(jù)Promise的結(jié)構(gòu),我們可以發(fā)現(xiàn)then()、catch()方法在它的原型上。
function MyPromise(fn) { this.PromiseState = 'pending' this.PromiseResult = undefined; function resolve(data) { } function reject(error) { } } MyPromise.prototype.then = function(thenCallback) { } MyPromise.prototype.catch = function(catchCallback) { }
上述代碼很簡(jiǎn)單,就定義了一個(gè)Promise的構(gòu)造函數(shù),有2個(gè)屬性(PromiseState、PromiseResult)和2個(gè)方法(resolve、reject)。
原型上增加了then方法和catch方法,且這2個(gè)方法都接收一個(gè)函數(shù)。
而每次通過(guò)new來(lái)創(chuàng)建Promise的函數(shù)時(shí),傳入的函數(shù)會(huì)執(zhí)行,因此我們直接調(diào)用fn函數(shù),并傳入resolve和reject這2個(gè)函數(shù)。
resolve和reject初步實(shí)現(xiàn)
resolve的調(diào)用會(huì)更改promise的狀態(tài)和值,且狀態(tài)是不可逆的。也就是說(shuō),只能從pending變成fulfilled或者rejected。而resolve函數(shù)的參數(shù)值會(huì)變成promise實(shí)例的值,reject同理。 所以我們把resolve和reject簡(jiǎn)單的寫完整.
function MyPromise(fn) { this.PromiseState = "pending"; this.PromiseResult = undefined; // 保存實(shí)例對(duì)象的this的值 const self = this; function resolve(data) { // 如果不使用self,這里內(nèi)部的this會(huì)指向window // 如果當(dāng)前的promise實(shí)例不是pending的狀態(tài)就退出了,否則就更改當(dāng)前的promise實(shí)例的狀態(tài)和值 if (self.PromiseState !== "pending") { return; } // 1.修改對(duì)象的狀態(tài)([[promiseState]]) // 2.設(shè)置對(duì)象結(jié)果值([[promiseResult]]) self.PromiseState = "fulfilled"; self.PromiseResult = data; } function reject(error) { if (self.PromiseState !== "pending") { return; } self.PromiseState = "rejected"; self.PromiseResult = error; } fn(resolve, reject); }
上面代碼中,resolve和reject就是用來(lái)更改當(dāng)前實(shí)例的狀態(tài)的,如果當(dāng)前狀態(tài)已經(jīng)改變了,即不為pending,那么就不再進(jìn)行狀態(tài)變更和值變更了。
接下來(lái)就是驗(yàn)證一下:
const p = new MyPromise((resolve, reject) => { resolve(1); reject(2); }); console.log(p);
發(fā)現(xiàn)我們執(zhí)行了resolve后再執(zhí)行reject并不會(huì)再次更改狀態(tài)。
但是還有一點(diǎn),如果我們不執(zhí)行resolve或者reject,而是直接執(zhí)行throw呢?
先看看原生的Promise效果。
const p1 = new Promise((resolve, reject) => { throw 111; }); console.log(p1);
發(fā)現(xiàn)狀態(tài)會(huì)變成rejected。
那我們是不是可以在執(zhí)行fn(resolve,reject)的時(shí)候進(jìn)行異常處理,將狀態(tài)變成rejected,值變成該異常信息。
// 如果throw異常,就需要捕獲到異常然后更改狀態(tài) try { // 同步調(diào)用執(zhí)行器函數(shù) fn(resolve, reject); } catch (e) { // 修改promise對(duì)象的狀態(tài)為失敗 reject(e); }
then方法的實(shí)現(xiàn)
then方法中我們知道它有2個(gè)參數(shù),且這2個(gè)參數(shù)都是函數(shù),第一個(gè)參數(shù)會(huì)在promise執(zhí)行resolve時(shí)調(diào)用,第二個(gè)參數(shù)會(huì)在promise執(zhí)行reject時(shí)調(diào)用。而.catch只不過(guò)是調(diào)用.then第二個(gè)參數(shù)的語(yǔ)法糖而已。
const p = new Promise((resolve, reject) => { resolve(1); }); const p1 = p.then( (res) => { console.log(res, "成功"); }, (err) => { console.log(err, "失敗"); } ); console.log(p, 111); console.log(p1, 222);
但是我們查看原生的Promise后,可以發(fā)現(xiàn),.then的執(zhí)行會(huì)返回一個(gè)新的Promise實(shí)例。而決定調(diào)用.then的第幾個(gè)參數(shù),則是根據(jù)調(diào)用then的那個(gè)promise實(shí)例的狀態(tài)決定。
修改代碼如下:
MyPromise.prototype.then = function (thenCallback, catchCallback) { return new Promise((resolve, reject) => { // 調(diào)用回調(diào)函數(shù),要根據(jù)當(dāng)前的promise實(shí)例來(lái)調(diào)用 if (this.PromiseState === "fulfilled") { const result = thenCallback(this.PromiseResult); resolve(result); } if (this.PromiseState === "rejected") { const result = catchCallback(this.PromiseResult); resolve(result); } }); };
我們的自定義函數(shù)上的原型的then返回了一個(gè)新的promise實(shí)例,而新的promise實(shí)例調(diào)用then的第幾個(gè)參數(shù)則根據(jù)調(diào)用then的promise實(shí)例的狀態(tài)決定(此處的this指向調(diào)用then的那個(gè)promise實(shí)例)。
我們需要拿到回調(diào)函數(shù)的執(zhí)行結(jié)果,然后再放入新的promise實(shí)例的resolve中更改新實(shí)例的狀態(tài)和值。
查看一下我們自己的效果:
const p = new MyPromise((resolve, reject) => { reject(1); }); const p1 = p.then( (res) => { console.log(res, "成功"); }, (err) => { console.log(err, "失敗"); } ); console.log(p, 111); console.log(p1, 222);
這時(shí)候可能有人就會(huì)提出疑問(wèn),如果在上述的p中的回調(diào)里延時(shí)執(zhí)行resolve或者reject呢?
const p = new MyPromise((resolve, reject) => { setTimeout(() => { resolve(1); }, 1000); }); const p1 = p.then( (res) => { console.log(res, "成功"); }, (err) => { console.log(err, "失敗"); } ); console.log(p, 111); console.log(p1, 222);
我們可以發(fā)現(xiàn)p1的狀態(tài)變成了pending。
這是因?yàn)楫?dāng)執(zhí)行到setTimeout的時(shí)候,發(fā)現(xiàn)是一個(gè)異步函數(shù),然后會(huì)將這個(gè)函數(shù)掛起,繼續(xù)執(zhí)行下面的.then(),然后當(dāng)時(shí)的p的狀態(tài)是pendding,因?yàn)椴粫?huì)執(zhí)行任何代碼。
那我們當(dāng)然是要加一個(gè)pendding的判斷啦!
可是該怎么實(shí)現(xiàn)判斷的內(nèi)部代碼呢?
首先我們先來(lái)思考一下,promise是一個(gè)對(duì)象,他是按地址引用的。我們希望在定時(shí)器時(shí)間到的時(shí)候再去更改這個(gè)新的promise的狀態(tài)和值。因此我們需要訪問(wèn)到上一個(gè)promise的狀態(tài)和值,并且在resolve或者reject執(zhí)行的時(shí)候訪問(wèn)到,而不是定時(shí)器掛起的時(shí)候。
function MyPromise(fn) { this.PromiseState = "pending"; this.PromiseResult = undefined; this.callback = {}; // 保存實(shí)例對(duì)象的this的值 const self = this; function resolve(data) { if (self.PromiseState !== "pending") { return; } // 1.修改對(duì)象的狀態(tài)([[promiseState]]) // 2.設(shè)置對(duì)象結(jié)果值([[promiseResult]]) self.PromiseState = "fulfilled"; self.PromiseResult = data; if (self.callback.onResolved) { self.callback.onResolved(data); } } function reject(error) { if (self.PromiseState !== "pending") { return; } self.PromiseState = "rejected"; self.PromiseResult = error; if (self.callback.onReject) { self.callback.onReject(error); } } // 如果throw異常,就需要捕獲到異常然后更改狀態(tài) try { // 同步調(diào)用執(zhí)行器函數(shù) fn(resolve, reject); } catch (e) { // 修改promise對(duì)象的狀態(tài)為失敗 reject(e); } } MyPromise.prototype.then = function (thenCallback, catchCallback) { return new Promise((resolve, reject) => { // 調(diào)用回調(diào)函數(shù),要根據(jù)當(dāng)前的promise實(shí)例來(lái)調(diào)用 if (this.PromiseState === "fulfilled") { const result = thenCallback(this.PromiseResult); resolve(result); } if (this.PromiseState === "rejected") { const result = catchCallback(this.PromiseResult); resolve(result); } // 判斷pending狀態(tài) if (this.PromiseState === "pending") { // 保存回調(diào)函數(shù) this.callback = { onResolved: function (data) { let result = thenCallback(data); resolve(result); }, onRejected: function (error) { let result = catchCallback(error); resolve(result); }, }; } }); };
const p = new MyPromise((resolve, reject) => { setTimeout(() => { resolve(1); }, 1000); }); const p1 = p.then( (res) => { console.log(res, "成功"); }, (err) => { console.log(err, "失敗"); } ); console.log(p, 111); console.log(p1, 222);
因?yàn)閚ew Promise的實(shí)例中遇到了異步的setTimeout會(huì)將內(nèi)部的程序掛起,繼續(xù)執(zhí)行.then。
而這時(shí)promise實(shí)例的狀態(tài)還是pending,因此我們需要對(duì)pending的狀態(tài)進(jìn)行處理,我們主要目的是,在setTimeout的回調(diào)函數(shù)執(zhí)行的時(shí)候,能夠執(zhí)行.then的函數(shù)參數(shù)。
這時(shí)候就需要進(jìn)行一個(gè)巧妙的設(shè)計(jì),我們需要在MyPromise構(gòu)造函數(shù)中增加一個(gè)callback的屬性,他是一個(gè)對(duì)象。
同時(shí)我們需要在pending的時(shí)候在.then里面將then的兩個(gè)參數(shù)傳給callback對(duì)象,同時(shí)傳入resolve的值或者是reject的值。
在pending的時(shí)候我們將函數(shù)傳給了實(shí)例的callback,當(dāng)被掛起的setTimeout回調(diào)函數(shù)執(zhí)行的時(shí)候,這時(shí)候callback已經(jīng)有值了,所以會(huì)根據(jù)resolve或者是reject去執(zhí)行對(duì)應(yīng)的函數(shù),并且將promise的實(shí)例的值傳給對(duì)應(yīng)的函數(shù)。
那如我我對(duì)p多次調(diào)用.then或者.catch呢?
const p = new MyPromise((resolve, reject) => { setTimeout(() => { resolve(1); }, 1000); }); const p1 = p.then( (res) => { console.log(res, "成功"); }, (err) => { console.log(err, "失敗"); } ); const p2 = p.then((res) => { console.log(res, "成功2"); }); console.log(p1, p2);
我們發(fā)現(xiàn)我們的值執(zhí)行了一次,那我們看一下原生的,可以發(fā)現(xiàn)會(huì)執(zhí)行2次。
const p = new Promise((resolve, reject) => { setTimeout(() => { resolve(1); }, 1000); }); const p1 = p.then( (res) => { console.log(res, "成功"); }, (err) => { console.log(err, "失敗"); } ); const p2 = p.then((res) => { console.log(res, "成功2"); }); console.log(p1, p2);
原因很簡(jiǎn)單,因?yàn)槲覀兊腸allback屬性是一個(gè)對(duì)象,每次執(zhí)行.then都會(huì)覆蓋當(dāng)前實(shí)例原先的callback。
怎么結(jié)局呢?很簡(jiǎn)單,我們只要將每次的pending時(shí)設(shè)置callback改成向數(shù)組加入對(duì)象就好。
調(diào)用時(shí)我們通過(guò)遍歷去調(diào)用就好了。
function MyPromise(fn) { this.PromiseState = "pending"; this.PromiseResult = undefined; this.callbacks = []; // 保存實(shí)例對(duì)象的this的值 const self = this; function resolve(data) { if (self.PromiseState !== "pending") { return; } // 1.修改對(duì)象的狀態(tài)([[promiseState]]) // 2.設(shè)置對(duì)象結(jié)果值([[promiseResult]]) self.PromiseState = "fulfilled"; self.PromiseResult = data; //調(diào)用成功的回調(diào)函數(shù) self.callbacks.forEach((item) => { item.onResolved(data); }); } function reject(error) { if (self.PromiseState !== "pending") { return; } self.PromiseState = "rejected"; self.PromiseResult = error; //執(zhí)行失敗的回調(diào) self.callbacks.forEach((item) => { item.onRejected(error); }); } // 如果throw異常,就需要捕獲到異常然后更改狀態(tài) try { // 同步調(diào)用執(zhí)行器函數(shù) fn(resolve, reject); } catch (e) { // 修改promise對(duì)象的狀態(tài)為失敗 reject(e); } } MyPromise.prototype.then = function (thenCallback, catchCallback) { return new Promise((resolve, reject) => { // 調(diào)用回調(diào)函數(shù),要根據(jù)當(dāng)前的promise實(shí)例來(lái)調(diào)用 if (this.PromiseState === "fulfilled") { const result = thenCallback(this.PromiseResult); resolve(result); } if (this.PromiseState === "rejected") { const result = catchCallback(this.PromiseResult); resolve(result); } // 判斷pending狀態(tài) if (this.PromiseState === "pending") { // 保存回調(diào)函數(shù) this.callbacks.push({ onResolved: thenCallback, onRejected: catchCallback, }); } }); };
const p = new MyPromise((resolve, reject) => { setTimeout(() => { resolve(1); }, 1000); }); const p1 = p.then( (res) => { console.log(res, "成功"); }, (err) => { console.log(err, "失敗"); } ); const p2 = p.then((res) => { console.log(res, "成功2"); }); console.log(p1, p2);
然后我們就發(fā)現(xiàn)我們可以正常地調(diào)用了。
那如果.then返回的值是一個(gè)promise呢?
這時(shí)候我們就需要考慮一下,如果.then返回時(shí)一個(gè)promise實(shí)例或者是一個(gè)throw錯(cuò)誤呢?
const p = new Promise((resolve, reject) => { resolve(1); }); const p1 = p.then( (res) => { console.log(res, "成功"); return new Promise((r, j) => { r(res); }); }, (err) => { console.log(err, "失敗"); } ); console.log(p1, "p1");
我們先看一下原生的效果,發(fā)現(xiàn)他時(shí)拿到了返回的promise的值。
那是不是就是在調(diào)用then的回調(diào)函數(shù)的時(shí)候判斷一下返回的是不是一個(gè)promise,如果是promise我們?cè)谶M(jìn)行特殊處理。
// 將.then的判定方式改成如下 if (this.PromiseState === "fulfilled") { try { const result = thenCallback(this.PromiseResult); if (result instanceof MyPromise) { result.then( (r) => { resolve(r); }, (j) => { reject(j); } ); } else { resolve(result); } } catch (e) { reject(e); } } if (this.PromiseState === "rejected") { try { const result = catchCallback(this.PromiseResult); if (result instanceof MyPromise) { result.then( (r) => { resolve(r); }, (j) => { reject(j); } ); } else { resolve(result); } } catch (e) { reject(e); } }
如果.then的回掉函數(shù)執(zhí)行后返回的是一個(gè)promise實(shí)例,但是我們.then默認(rèn)就返回了一個(gè)實(shí)例,我們就直接取這個(gè)實(shí)例的resolve值或者是reject值,將返回值給then默認(rèn)返回的promise實(shí)例。
異步方式同理,但是要注意this的指向問(wèn)題。
// 判斷pending狀態(tài) if (this.PromiseState === "pending") { // 保存回調(diào)函數(shù) this.callbacks.push({ onResolved: function () { try { // 這里的self指向的是調(diào)用.then的promise實(shí)例 let result = thenCallback(self.PromiseResult); //判斷 if (result instanceof Promise) { result.then( (v) => { resolve(v); }, (r) => { reject(r); } ); } else { resolve(result); } } catch (e) { reject(e); } }, onRejected: function () { try { // 這里的self指向的是調(diào)用.then的promise實(shí)例 let result = catchCallback(self.PromiseResult); //判斷 if (result instanceof Promise) { result.then( (v) => { resolve(v); }, (r) => { reject(r); } ); } else { resolve(result); } } catch (e) { reject(e); } }, }); } });
我們發(fā)現(xiàn),代碼已經(jīng)重復(fù)了4次,我們就可以進(jìn)行一個(gè)封裝。
MyPromise.prototype.then = function (thenCallback, catchCallback) { const self = this; return new Promise((resolve, reject) => { function run(type) { try { //獲取回調(diào)函數(shù)的執(zhí)行結(jié)果 let result = type(self.PromiseResult); //判斷 if (result instanceof Promise) { //如果是 Promise 類型的對(duì)象 result.then( (v) => { resolve(v); }, (j) => { reject(j); } ); } else { //結(jié)果的對(duì)象狀態(tài)為『成功』 resolve(result); } } catch (e) { reject(e); } } // 調(diào)用回調(diào)函數(shù),要根據(jù)當(dāng)前的promise實(shí)例來(lái)調(diào)用 if (this.PromiseState === "fulfilled") { run(thenCallback); } if (this.PromiseState === "rejected") { run(catchCallback); } // 判斷pending狀態(tài) if (this.PromiseState === "pending") { // 保存回調(diào)函數(shù) this.callbacks.push({ onResolved: function () { run(thenCallback); }, onRejected: function () { run(catchCallback); }, }); } }); };
嗯,封裝完后的一個(gè)完整的.then。我們先看一下完整的效果。
const p1 = p.then( (res) => { console.log(res, "成功"); return new Promise((r, j) => { r(res); }); }, (err) => { console.log(err, "失敗"); } ); console.log(p1, "p1");
和原生的基本上是一模一樣了。
接下來(lái)就是對(duì)catch的實(shí)現(xiàn)了
但是我們知道,catch其實(shí)就是.then執(zhí)行第二個(gè)參數(shù)的一個(gè)語(yǔ)法糖。 因此,我們就可以將接收到的回調(diào)函數(shù)直接給.then的第二個(gè)參數(shù)。
MyPromise.prototype.catch = function(onRejected){ return this.then(undefined, onRejected); }
這時(shí)候我們就要注意了,我們給then的第一個(gè)參數(shù)賦值了一個(gè)undefined。但是我們并沒(méi)有對(duì)undefined進(jìn)行處理。而且我們?cè)腜romise是可以傳入其他數(shù)據(jù)的,不一定是一個(gè)回調(diào)函數(shù)。
因此,我們需要在MyPromise的原型里的.then方法進(jìn)行一個(gè)判斷:
if (typeof catchCallback !== "function") { catchCallback = (reason) => { throw reason; }; } if (typeof thenCallback !== "function") { thenCallback = (value) => value; }
如果傳入的不是一個(gè)函數(shù),我們就將它變成一個(gè)函數(shù),并且獲取的是上一個(gè).then返回的promise實(shí)例的值。
總體上我們大致完成了,但是Promise還存在構(gòu)造函數(shù)的方法Promise.resolve(value)
和Promise.reject(error)
這個(gè)就很簡(jiǎn)單了
//添加 resolve 方法 MyPromise.resolve = function(value){ //返回promise對(duì)象 return new MyPromise((r, j) => { if(value instanceof MyPromise){ value.then(v=>{ r(v); }, r=>{ j(r); }) }else{ //狀態(tài)設(shè)置為成功 resolve(value); } }); }
判斷resolve傳入的值是否是一個(gè)MyPromise實(shí)例,如果是,則根據(jù)這個(gè)Promise的狀態(tài)來(lái)返回,如果不是則直接調(diào)用resolve()
reject同理:
//添加 reject 方法 MyPromise.reject = function(error){ return new MyPromise((resolve, reject)=>{ reject(error); }); }
Promise.all的實(shí)現(xiàn)
Promise.all的實(shí)現(xiàn)基于我們?cè)确庋b的MyPromise。
我們先來(lái)分析一下原先的Promise.all的方法,它接受一個(gè)promise數(shù)組,返回一個(gè)新的promise。如果數(shù)組中有一個(gè)狀態(tài)是rejected,那將直接返回一個(gè)rejected的promise實(shí)例。如果都成功了,則返回成功的promise。
MyPromise.all = function (promiseLists) { return new Promise((resolve, reject) => { let promiseResults = []; let count = 0; for (let i = 0; i < promiseLists.length; i++) { promiseLists.then( (v) => { count += 1; promiseResults[i] = v; if (count === promiseLists.length) { resolve(promiseResults); } }, (err) => { reject(err); } ); } }); };
實(shí)現(xiàn)上我們定義了一個(gè)promiseLists的形參用來(lái)接收promise的數(shù)組。因?yàn)榉祷氐目隙ㄊ且粋€(gè)promise,所以我們直接返回了一個(gè)promise的實(shí)例。
我們定義了一個(gè)count用來(lái)計(jì)數(shù)成功執(zhí)行的個(gè)數(shù),promiseResults則用來(lái)接收成功的結(jié)果(要按照順序接收)。最后就是遍歷promiseLists的數(shù)組了,如果是resolve則count+1,并且將值往promiseResults里面塞。如果count的值和接受的數(shù)組長(zhǎng)度一樣了,那就是全部的promise返回了fulfilled。如果有一個(gè)錯(cuò)誤,則直接退出,并且將錯(cuò)誤的promise的值傳給all返回的promise。
到此這篇關(guān)于JavaScript Promise執(zhí)行流程深刻理解的文章就介紹到這了,更多相關(guān)JavaScript Promise內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于預(yù)加載InstantClick的問(wèn)題解決方法
本篇文章主要介紹了關(guān)于預(yù)加載InstantClick的問(wèn)題解決方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09javascript簡(jiǎn)單拖拽實(shí)現(xiàn)代碼(鼠標(biāo)事件 mousedown mousemove mouseup)
javascript簡(jiǎn)單拖拽,簡(jiǎn)單拖拽實(shí)現(xiàn)2012-05-05js實(shí)現(xiàn)增加數(shù)字顯示的環(huán)形進(jìn)度條效果
本文主要分享了js實(shí)現(xiàn)增加數(shù)字顯示的環(huán)形進(jìn)度條效果的示例代碼。具有一定的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-02-02Base64(二進(jìn)制)圖片編碼解析及在各種瀏覽器的兼容性處理
這篇文章主要介紹了Base64(二進(jìn)制)圖片編碼解析及在各種瀏覽器的兼容性處理,需要的朋友可以參考下2017-02-02優(yōu)雅而高效的JavaScript?try...catch語(yǔ)句詳解(js異常處理)
這篇文章主要給大家介紹了關(guān)于JavaScript中try...catch語(yǔ)句的相關(guān)資料,也就是js異常處理方法,try...catch是JavaScript中的錯(cuò)誤處理機(jī)制,它的作用是捕獲和處理可能發(fā)生的錯(cuò)誤,以避免程序崩潰,需要的朋友可以參考下2024-01-01