javascript
JavaScript中错误正确处理方式,你用对了吗?
JavaScript的事件驅(qū)動范式增添了豐富的語言,也是讓使用JavaScript編程變得更加多樣化。如果將瀏覽器設(shè)想為JavaScript的事件驅(qū)動工具,那么當(dāng)錯誤發(fā)生時,某個事件就會被拋出。理論上可以認(rèn)為這些發(fā)生的錯誤只是JavaScript中的簡單事件。
本文將會討論客戶端JavaScript中的錯誤處理。主要介紹JavaScript中的易犯錯誤、錯誤處理、異步代碼編寫等內(nèi)容。
下面就讓我們一起看看如何正確處理JavaScript中的錯誤。
Deferred 和 Promise
ES6 和 jQuery 都有 Deffered 和 Promise,但是略有不同。不過它們的作用可以簡單的用兩句話來描述
Deffered 觸發(fā) resolve 或 reject
Promise 中申明 resolve 或 reject 后應(yīng)該做什么(回調(diào))
在 jQuery 中
var deferred = $.Deferred();
var promise = deferred.promise();
在 ES6 中
var deferred = Promise.defer();
var promise= defered.promise;
MDN 宣布 Deferred 在 Gecko 30 中被申明為過期,不應(yīng)該再使用,而應(yīng)該用 new Promise() 來代替。關(guān)于 new Promise() 將在后面說明。
jQuery 的 Deferred/Promise
jQuery 中最常用的 Promise 對象是 $.ajax() 返回的,最常用的方法不是 then,而是 done、fail 和 always。除了 $.ajax() 外,jQuery 也提供了 $.get()、$.post() 和 $.getJSON() 等簡化 Ajax 調(diào)用,它們返回的和 $.ajax() 的返回值一樣,是個 Promise 對象。
實際上 $.ajax() 返回的是一個 jqXHR 對象。但 jqXHR 實現(xiàn)了 jQuery 的 Promise 接口,所以也是一個 Promise 對象。
done()、fail() 和 always()
done() 添加 deferred.resolve() 的回調(diào),fail() 添加 deferred.reject() 的回調(diào)。所以在 Ajax 調(diào)用成功的情況下執(zhí)行 done() 添加的回調(diào),調(diào)用失敗時執(zhí)行 fail() 添加的回調(diào)。但不管成功與否,都會執(zhí)行 always() 添加的回調(diào)。
這里 done()、fail() 和 always() 都是以類似事件的方式添加回調(diào),也就意味著,不管執(zhí)行多次次 done()、fail() 或 always(),它們添加的若干回調(diào)都會在符合的條件下依次執(zhí)行。
一般情況下會這樣執(zhí)行 Ajax
// 禁用按鈕以避免重復(fù)提交
$("#theButton").prop({
disabled: true
});
// 調(diào)用 Ajax 提交數(shù)據(jù),假設(shè)返回的是 JSON 數(shù)據(jù)
var jqxhr = $.ajax("do/example", {
type: "post",
dataType: "json",
data: getFormData()
});
jqxhr.done(function(jsonObject) {
// Ajax 調(diào)用成功
console.log("success with data", jsonObject);
}).fail(function() {
// Ajax 調(diào)用失敗
console.log("failed")
}).always(function() {
// 不管成功與否,都會執(zhí)行,取消按鈕的禁用狀態(tài)
$("#theButton").prop({
disabled: false
});
});
上面是最普通最常用的用法,但是在一個項目中總是這么寫 Ajax,有點累,稍微約定一下再封裝一下就使用起來就會便捷得多。首先,假設(shè)我們定義返回的 JSON 是這樣的格式:
{
"code": "int, 0 表示成功,其它值表示出錯",
"message": "string, 附加的消息,可選",
"data": "object,附加的數(shù)據(jù),可選
}
然后為項目公共類 app 定義一個 ajax 方法
app.ajax = function(button, url, data) {
if (button) {
button.prop("disabled", true);
}
return $.ajax(url, {
type: "post",
dataType: "json",
data: data
}).done(function(json) [
if (json.code !== 0) {
showError(json.message || "操作發(fā)生錯誤");
}
}).fail(function() {
showError("服務(wù)器錯誤,請稍后再試");
}).always(function() {
if (button) {
button.prop("disabled", false);
}
});
};
// 調(diào)用
app.ajax("do/example", getFormData()).done(function(json) {
if (json.code === 0) {
// 只需要處理正確的情況啦
}
});
不過還是有點不爽,如果不需要判斷 json.code === 0 就更好了。這個……可以自己用一個 Deferred 來處理:
app.ajax = function(button, url, data) {
if (button) {
button.prop("disabled", true);
}
var deferred = $.Deferred();
$.ajax(url, {
type: "post",
dataType: "json",
data: data
}).done(function(json) [
if (json.code !== 0) {
showError(json.message || "操作發(fā)生錯誤");
deferred.reject();
} else {
deferred.resolve(json);
}
}).fail(function() {
showError("服務(wù)器錯誤,請稍后再試");
deferred.reject();
}).always(function() {
if (button) {
button.prop("disabled", false);
}
});
return deferred.promise();
};
// 調(diào)用
app.ajax("do/example", getFormData()).done(function(json) {
// json.code === 0 總是成立
// 正常處理 json.data 就好
});
注意,這里已經(jīng)不是直接返回 $.ajax() 的結(jié)果 jqXHR 對象了,返回的是新建 Deferred 對象的 promise對象。
復(fù)習(xí)了 Ajax,現(xiàn)在需要切入正題,找到 jQuery Promise 和 ES6 Promise 接近的地方——then()。
jQuery deferred.then() 鄭州不孕不育醫(yī)院:http://wapyyk.39.net/zz3/zonghe/1d427.html
在 jQuery 1.8 以前(不含 1.8,比如 jQuery 1.7.2),deferred.then() 就是一個把 done() 和 fail() 放在一起的語法糖。jQuery 在 1.8 版本的時候修改了 deferred.then() 的行為,使 then() 的行為與 Promise 的 then() 相似。從 jQuery 的文檔可以看到 1.8 版本的變化——干掉了 callback,換成了 filter:
// version added: 1.5, removed: 1.8
deferred.then( doneCallbacks, failCallbacks )
// version added: 1.7, removed: 1.8
deferred.then( doneCallbacks, failCallbacks [, progressCallbacks ] )
// version added: 1.8
deferred.then( doneFilter [, failFilter ] [, progressFilter ] )
可以簡單的把 callback 當(dāng)作一個事件處理,值用于 callback 之后一般不會改變;而 filter 不同,一個值傳入 filter 再從 filter 返回出來,可能已經(jīng)變了。還是舉個例子來說明
var deferred = $.Deferred();
var promise = deferred.promise();
promise.then(function(v) {
console.log(`then with ${v}`);
}).done(function(v) {
console.log(`done with ${v}`);
});
deferred.resolve("resolveData");
在 jQuery 1.7.2 中的結(jié)果
then with resolveData
done with resolveData
在 jQuery 1.8.0 中的結(jié)果
then with resolveData
done with undefined
從上面來看,jQuery 的 deferred.then() 語義和 ES6 Promise.then() 語義基本一致。如果把上面的 app.ajax 換成 then() 實現(xiàn)會有助于對 ES6 Promise 的理解。
app.ajax = function(button, url, data) {
if (button) {
button.prop("disabled", true);
}
return $.ajax(url, {
type: "post",
dataType: "json",
data: data
}).then(function(json) {
if (json.code !== 0) {
showError(json.message || "操作發(fā)生錯誤");
return $.Deferred().reject().promise();
} else {
return $.Deferred().resolve(json).promise();
}
}, function() {
showError("服務(wù)器錯誤,請稍后再試");
deferred.reject();
}).always(function() {
if (button) {
button.prop("disabled", false);
}
});
};
// 調(diào)用方式?jīng)]變,用 done,也可以用 then
app.ajax("do/example", getFormData()).done(function(json) {
// json.code === 0 總是成立
// 正常處理 json.data 就好
});
從 jQuery Promise 到 ES6 Promise
上面的代碼太長,提煉一下關(guān)鍵部分(示意,不能運行)
var promise = $.ajax();
promise.then(function(data) {
// resolve
return data.code
? new Promise().reject()
: new Promise().resolve(data);
// 如果沒有錯,就返回一個新的 promise,并使用 data 來 resolve,
// 也可以直接返回 data,
// 這樣后面 then 的 resolve 部分才能收到數(shù)據(jù)
}, function() {
// rejected
});
// 調(diào)用階段
promise.then(function(data) {
// 處理 data
});
也許你沒注意到,其實上面的代碼基本上就是 ES6 的 Promise 了。下面正式用 ES6 Promise 改寫上面的示意代碼
var promise = new Promise(function(resolve, reject) {
$.ajax().then(resolve, reject);
// 上面這句沒看懂?那換成這樣你一定會懂
// $.ajax().then(function(data) {
// resolve(data);
// }, function() {
// reject();
// });
}).then(function(data) {
return data.code
? Promise.reject()
: Promise.resolve(data);
// 這里 Promise.resolve(data) 同樣可以直接替換為 data
});
// 調(diào)用沒變
promise.then(function(data) {
// 處理 data
});
怎么樣,差別不大吧。不知不覺就會 ES6 Promise 了!
ES6 的 Promise
上面已經(jīng)把 ES6 的 Promise 帶出來了,現(xiàn)在只需要把常用方法列出來作為參考即可
注意,小寫的 promise 表示 Promise 對象
new Promise(executor),產(chǎn)生一個新的 Promise 對象
executor(resolve, reject)
executor、resolve 和 reject 均為函數(shù),在 executor 中,正確處理調(diào)用 resolve() 返回數(shù)據(jù),異常處理直接 throw new Error(...) 或調(diào) reject() 返回數(shù)據(jù)。
Promise.resolve(data),產(chǎn)生 Promise 對象并 resolve
Promise.reject(),產(chǎn)生 Promise 對象并 reject
promise.then(onResolve, onReject),然后……繼續(xù)處理
promise.catch(onReject),project.then(null, onReject) 的語法糖,和 jQuery 的 promise.fail()差不多(但不同)。
轉(zhuǎn)載于:https://www.cnblogs.com/dream8023/p/10824337.html
超強干貨來襲 云風(fēng)專訪:近40年碼齡,通宵達旦的技術(shù)人生總結(jié)
以上是生活随笔為你收集整理的JavaScript中错误正确处理方式,你用对了吗?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 吴裕雄 python 神经网络——Ten
- 下一篇: python简单爬豆瓣电影排名