国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

js-Promise

xcold / 1946人閱讀

摘要:總結(jié)用方法創(chuàng)建對(duì)象用或添加對(duì)象的處理函數(shù)它的作用是為實(shí)例添加狀態(tài)改變時(shí)的回調(diào)函數(shù)。方法是的別名,用于指定發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù)。

一、為什么需要Promise

Javascript 采用回調(diào)函數(shù)(callback)來處理異步編程。從同步編程到異步回調(diào)編程有一個(gè)適應(yīng)的過程,但是如果出現(xiàn)多層回調(diào)嵌套,也就是我們常說的回調(diào)金字塔(Pyramid of Doom),絕對(duì)是一種糟糕的編程體驗(yàn)。于是便有了 Promises/A , Promises/A +等規(guī)范,用于解決回調(diào)金字塔問題。

    // 回調(diào)金字塔
    request("test1.html", "", function(data1) {
        console.log("第一次請(qǐng)求成功, 這是返回的數(shù)據(jù):", data1);
        request("test2.html", data1, function (data2) {
            console.log("第二次請(qǐng)求成功, 這是返回的數(shù)據(jù):", data2);
            request("test3.html", data2, function (data3) {
                console.log("第三次請(qǐng)求成功, 這是返回的數(shù)據(jù):", data3);
                //request... 繼續(xù)請(qǐng)求
            }, function(error3) {
                console.log("第三次請(qǐng)求失敗, 這是失敗信息:", error3);
            });
        }, function(error2) {
            console.log("第二次請(qǐng)求失敗, 這是失敗信息:", error2);
        });
    }, function(error1) {
        console.log("第一次請(qǐng)求失敗, 這是失敗信息:", error1);
    });
    
    // 引入 Promise 之后
    sendRequest("test1.html", "").then(function(data1) {
        console.log("第一次請(qǐng)求成功, 這是返回的數(shù)據(jù):", data1);
    }).then(function(data2) {
        console.log("第二次請(qǐng)求成功, 這是返回的數(shù)據(jù):", data2);
    }).then(function(data3) {
        console.log("第三次請(qǐng)求成功, 這是返回的數(shù)據(jù):", data3);
    }).catch(function(error) {
        //用catch捕捉前面的錯(cuò)誤
        console.log("sorry, 請(qǐng)求失敗了, 這是失敗信息:", error);
    });

什么是Promise?
一個(gè) Promise 對(duì)象代表一個(gè)目前還不可用,但是在未來的某個(gè)時(shí)間點(diǎn)可以被解析的值。Promise表示一個(gè)異步操作的最終結(jié)果。

二、Promise/A+基本的規(guī)范

一個(gè)Promise可能有三種狀態(tài):初始狀態(tài)(pending)、已完成(fulfilled)、已拒絕(rejected)。pending 狀態(tài)的 Promise 對(duì)象可能觸發(fā)fulfilled 狀態(tài)并傳遞一個(gè)值給相應(yīng)的狀態(tài)處理方法,也可能觸發(fā)失敗狀態(tài)(rejected)并傳遞失敗信息。當(dāng)其中任一種情況出現(xiàn)時(shí),Promise 對(duì)象的 then 方法綁定的處理方法(handlers )就會(huì)被調(diào)用(then方法包含兩個(gè)參數(shù):onfulfilled 和 onrejected,它們都是 Function 類型。當(dāng)Promise狀態(tài)為fulfilled時(shí),調(diào)用 then 的 onfulfilled 方法,當(dāng)Promise狀態(tài)為rejected時(shí),調(diào)用 then 的 onrejected 方法, 所以在異步操作的完成和綁定處理方法之間不存在競(jìng)爭(zhēng))。

一個(gè)Promise的狀態(tài)只可能從“等待”轉(zhuǎn)到“完成”態(tài)或者“拒絕”態(tài),不能逆向轉(zhuǎn)換,同時(shí)“完成”態(tài)和“拒絕”態(tài)不能相互轉(zhuǎn)換。

Promise必須實(shí)現(xiàn)then方法(可以說,then就是promise的核心),而且then必須返回一個(gè)Promise,同一個(gè)Promise的then可以調(diào)用多次,并且回調(diào)的執(zhí)行順序跟它們被定義時(shí)的順序一致。

then方法接受兩個(gè)參數(shù),第一個(gè)參數(shù)是成功時(shí)的回調(diào),在Promise由“等待”態(tài)轉(zhuǎn)換到“完成”態(tài)時(shí)調(diào)用,另一個(gè)是失敗時(shí)的回調(diào),在Promise由“等待”態(tài)轉(zhuǎn)換到“拒絕”態(tài)時(shí)調(diào)用。同時(shí),then可以接受另一個(gè)Promise傳入,也接受一個(gè)“類then”的對(duì)象或方法,即thenable對(duì)象。ajax就是一個(gè)thenable對(duì)象。

Promise狀態(tài)變化

優(yōu)點(diǎn)
有了 Promise 對(duì)象,就可以將異步操作以同步操作的流程表達(dá)出來,避免了層層嵌套的回調(diào)函數(shù)。此外,Promise 對(duì)象提供統(tǒng)一的接口,使得控制異步操作更加容易。

//不友好的層層嵌套
loadImg("a.jpg", function() {  
    loadImg("b.jpg", function() {  
        loadImg("c.jpg", function() {  
            console.log("all done!");  
        });  
    });  
});  

缺點(diǎn)
Promise 也有一些缺點(diǎn)。首先,無法取消 Promise,一旦新建它就會(huì)立即執(zhí)行,無法中途取消。其次,如果不設(shè)置回調(diào)函數(shù),Promise 內(nèi)部拋出的錯(cuò)誤,不會(huì)反應(yīng)到外部。第三,當(dāng)處于 Pending 狀態(tài)時(shí),無法得知目前進(jìn)展到哪一個(gè)階段(剛剛開始還是即將完成)。

三、ES6 Promise基本的API 1. Promise.resolve(value) // 生成一個(gè)成功的promise對(duì)象

返回一個(gè)狀態(tài)由給定value決定的Promise對(duì)象。如果該值是一個(gè)Promise對(duì)象,則直接返回該對(duì)象;如果該值是thenable(即,帶有then方法的對(duì)象),返回的Promise對(duì)象的最終狀態(tài)由then方法執(zhí)行決定;否則的話(該value為空,基本類型或者不帶then方法的對(duì)象),返回的Promise對(duì)象狀態(tài)為fulfilled,并且將該value傳遞給對(duì)應(yīng)的then方法。通常而言,如果你不知道一個(gè)值是否是Promise對(duì)象,使用Promise.resolve(value) 來返回一個(gè)Promise對(duì)象,這樣就能將該value以Promise對(duì)象形式使用。

2. Promise.reject(reason) // 生成錯(cuò)誤的一個(gè)promise對(duì)象

返回一個(gè)狀態(tài)為失敗的Promise對(duì)象,并將給定的失敗信息傳遞給對(duì)應(yīng)的處理方法

3. Promise.prototype.then() // 核心部分

返回一個(gè)新的Promise。

4. Promise.prototype.catch(onRejected) // 異常捕獲

添加一個(gè)拒絕(rejection) 回調(diào)到當(dāng)前 promise, 返回一個(gè)新的promise。當(dāng)這個(gè)回調(diào)函數(shù)被調(diào)用,新 promise 將以它的返回值來resolve,否則如果當(dāng)前promise 進(jìn)入fulfilled狀態(tài),則以當(dāng)前promise的完成結(jié)果作為新promise的完成結(jié)果.

5. Promise.all(iterable)

這個(gè)方法返回一個(gè)新的promise對(duì)象,該promise對(duì)象在iterable參數(shù)對(duì)象里所有的promise對(duì)象都成功的時(shí)候才會(huì)觸發(fā)成功,一旦有任何一個(gè)iterable里面的promise對(duì)象失敗則立即觸發(fā)該promise對(duì)象的失敗。這個(gè)新的promise對(duì)象在觸發(fā)成功狀態(tài)以后,會(huì)把一個(gè)包含iterable里所有promise返回值的數(shù)組作為成功回調(diào)的返回值,順序跟iterable的順序保持一致;如果這個(gè)新的promise對(duì)象觸發(fā)了失敗狀態(tài),它會(huì)把iterable里第一個(gè)觸發(fā)失敗的promise對(duì)象的錯(cuò)誤信息作為它的失敗錯(cuò)誤信息。Promise.all方法常被用于處理多個(gè)promise對(duì)象的狀態(tài)集合。(可以參考jQuery.when方法)

6. Promise.race(iterable) // 最先執(zhí)行的promise結(jié)果

當(dāng)iterable參數(shù)里的任意一個(gè)子promise被成功或失敗后,父promise馬上也會(huì)用子promise的成功返回值或失敗詳情作為參數(shù)調(diào)用父promise綁定的相應(yīng)句柄,并返回該promise對(duì)象。

如果有一個(gè)Promise對(duì)象執(zhí)行完成了,后面的還會(huì)不會(huì)再繼續(xù)執(zhí)行了呢?在ES6 Promises規(guī)范中,也沒有取消(中斷)Promise對(duì)象執(zhí)行的概念,我們必須要確保Promise最終進(jìn)入resolve or reject狀態(tài)之一。所以,后面的Promise對(duì)象還是會(huì)繼續(xù)執(zhí)行的。

四、ES6 Promise基本用法 1. 創(chuàng)建Promise對(duì)象。

new Promise(fn) 返回一個(gè)Promise對(duì)象

在 fn 中指定異步等處理。

處理結(jié)果正常的話,調(diào)用 resolve(處理結(jié)果值)。

處理結(jié)果錯(cuò)誤的話,調(diào)用 reject(Error對(duì)象)。

//示例
function getURL(URL) {
    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open("GET", URL);
        xhr.onload = () => resolve(xhr.responseText);
        xhr.onerror = () => reject(xhr.statusText);
        xhr.send();
    });
}
// 運(yùn)行示例
var URL = "http://baidu.com";    
getURL(URL)
.then(function onFulfilled(value){
    console.log(value); 
})
.catch(function onRejected(error){
    console.error(error);
});
// 其實(shí) .catch 只是 Promise.then(undefined, onRejected) 的別名而已,
// 如下代碼也可以完 成同樣的功能。
getURL(URL).then(onFulfilled, onRejected);
getURL(URL).then(function(value) {
    // fulfillment
    }, function(reason) {
    // rejection
});

總結(jié):
用 new Promise 方法創(chuàng)建promise對(duì)象
用 .then 或 .catch 添加promise對(duì)象的處理函數(shù)

2. Promise.prototype.then()

它的作用是為Promise實(shí)例添加狀態(tài)改變時(shí)的回調(diào)函數(shù)。前面說過,then方法的第一個(gè)參數(shù)是Resolved狀態(tài)的回調(diào)函數(shù),第二個(gè)參數(shù)(可選)是Rejected狀態(tài)的回調(diào)函數(shù)。

then方法返回的是一個(gè)新的Promise實(shí)例。因此可以采用鏈?zhǔn)綄懛ǎ磘hen方法后面再調(diào)用另一個(gè)then方法。

3. Promise.prototype.catch()

Promise.prototype.catch方法是.then(null, rejection)的別名,用于指定發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù)。

getAjax("url/info").then(function(data) {
    // ...
}).catch(function(error) {
    // 處理 ajax 和 前一個(gè)回調(diào)函數(shù)運(yùn)行時(shí)發(fā)生的錯(cuò)誤
    console.log("發(fā)生錯(cuò)誤!", error);
});

總結(jié):
1.上面代碼中,getAjax方法返回一個(gè) Promise 對(duì)象,如果該對(duì)象狀態(tài)變?yōu)镽esolved,則會(huì)調(diào)用then方法指定的回調(diào)函數(shù);如果異步操作拋出錯(cuò)誤,狀態(tài)就會(huì)變?yōu)镽ejected,就會(huì)調(diào)用catch方法指定的回調(diào)函數(shù),處理這個(gè)錯(cuò)誤。另外,then方法指定的回調(diào)函數(shù),如果運(yùn)行中拋出錯(cuò)誤,也會(huì)被catch方法捕獲。
2.Promise 對(duì)象的錯(cuò)誤具有“冒泡”性質(zhì),會(huì)一直向后傳遞,直到被捕獲為止。也就是說,錯(cuò)誤總是會(huì)被下一個(gè)catch語(yǔ)句捕獲。

有了then里面的第二個(gè)onRejected函數(shù)捕獲錯(cuò)誤,為什么還需要catch?

function throwError(value) { // 拋出異常
    throw new Error(value);
}
// <1> onRejected不會(huì)被調(diào)用
function main1(onRejected) {
    return Promise.resolve(1).then(throwError, onRejected);
}
// <2> 有異常發(fā)生時(shí)onRejected會(huì)被調(diào)用
function main2(onRejected) {
    return Promise.resolve(1).then(throwError).catch(onRejected);
}
// 執(zhí)行main函數(shù)
main1(function(){
    console.log("錯(cuò)誤異常");
}
// 執(zhí)行main2函數(shù)
main2(function(){
    console.log("錯(cuò)誤異常");
}
/*Promise.prototype.catch方法是.then(null, rejection)的別名,用于指定發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù)。
一般來說,不要在then方法里面定義Reject狀態(tài)的回調(diào)函數(shù)(即then的第二個(gè)參數(shù)),總是使用catch方法。
*/
Promise.resolve(1).then(throwError).then(null, onRejected);

在函數(shù)main1因?yàn)殡m然我們?cè)诘牡诙€(gè)參數(shù)中指定了用來錯(cuò)誤處理的函數(shù),但實(shí)際上它卻不能捕獲第一個(gè)參數(shù)指定的函數(shù)(本例為throwError)里面出現(xiàn)的錯(cuò)誤。
與此相對(duì)的是main2中的代碼則遵循了 throwError → onRejected 的調(diào)用流程。這時(shí)候出現(xiàn)異常的話,在會(huì)被方法鏈中的下一個(gè)方法,即 .catch 所捕獲,進(jìn)行相應(yīng)的錯(cuò)誤處理。

總結(jié):
.then 方法中的onRejected參數(shù)所指定的回調(diào)函數(shù),實(shí)際上針對(duì)的是其Promise對(duì)象或者之前的Promise對(duì)象,而不是針對(duì)方法里面指定的第一個(gè)參數(shù),即onFulfilled所指向的對(duì)象,這也是then和 catch表現(xiàn)不同的原因。

4. Promise.prototype.finally(onFinally)

添加一個(gè)事件處理回調(diào)于當(dāng)前promise對(duì)象,并且在原promise對(duì)象解析完畢后,返回一個(gè)新的promise對(duì)象。回調(diào)會(huì)在當(dāng)前promise運(yùn)行完畢后被調(diào)用,無論當(dāng)前promise的狀態(tài)是完成(fulfilled)還是失敗(rejected)

5. Promise.resolve()

有時(shí)需要將現(xiàn)有對(duì)象轉(zhuǎn)為Promise對(duì)象,Promise.resolve方法就起到這個(gè)作用。
該函數(shù)的參數(shù)四種情況:
(1)參數(shù)是一個(gè)Promise實(shí)例,那么Promise.resolve將不做任何操作,原封不動(dòng)的將實(shí)例返回。
(2)參數(shù)是一個(gè)thenable對(duì)象,會(huì)將其轉(zhuǎn)為Promise對(duì)象,然后立即執(zhí)行該對(duì)象的then方法。
(3)參數(shù)不是具有then方法的對(duì)象,或根本就不是對(duì)象。比如說字符之類,則Promise.resolve方法返回一個(gè)新的Promise對(duì)象,并且狀態(tài)Resolved。
(4)不帶有任何參數(shù),直接返回一個(gè)狀態(tài)為Resolved的Promise對(duì)象。

使用Promise.resolve()創(chuàng)建Promise對(duì)象

// 靜態(tài)方法 Promise.resolve(value) 可以認(rèn)為是 new Promise() 方法的快捷方式。
// 比如 
Promise.resolve(1)
.then(function(value){
    console.log(value);
});  
// 可以認(rèn)為是以下代碼的語(yǔ)法糖。
new Promise(function(resolve){ 
    resolve(1);
})
.then(function(value){
    console.log(value);
});
// 控制臺(tái)輸出1
注意:無論P(yáng)romise.resolve的參數(shù)是什么,只要變成了rejected或者resolved。都會(huì)執(zhí)行then里面的resolve函數(shù)。

resolve另一個(gè)promise對(duì)象

var original = Promise.resolve("我在第二行");
var cast = Promise.resolve(original);
cast.then(function(value) {
    console.log("value: " + value);
});
console.log("original === cast ? " + (original === cast));

/*
* 打印順序如下,這里有一個(gè)同步異步先后執(zhí)行的區(qū)別
* original === cast ? true
* value: 我在第二行
*/

將 thenable 對(duì)象轉(zhuǎn)換為promise對(duì)象。 什么是thenable對(duì)象?
簡(jiǎn)單來說它就是一個(gè)非常類似promise的東西。thenable指的是一個(gè)
具有 .then 方法的對(duì)象。jQuery.ajax(),這個(gè)對(duì)象具有 .then 方法。

// Resolve一個(gè)thenable對(duì)象
var p1 = Promise.resolve({ 
    then: function(onFulfill, onReject) { onFulfill("fulfilled!"); }
});
console.log(p1 instanceof Promise) // true, 這是一個(gè)Promise對(duì)象

p1.then(function(v) {
      console.log(v); // 輸出"fulfilled!"
    }, function(e) {
      // 不會(huì)被調(diào)用
});

// Thenable在callback之前拋出異常
// Promise rejects
var thenable = { then: function(resolve) {
    throw new TypeError("Throwing");
    resolve("Resolving");
}};

var p2 = Promise.resolve(thenable);
p2.then(function(v) {
    // 不會(huì)被調(diào)用
}, function(e) {
    console.log(e); // TypeError: Throwing
});

// Thenable在callback之后拋出異常
// Promise resolves
var thenable = { then: function(resolve) {
    resolve("Resolving");
    throw new TypeError("Throwing");
}};

var p3 = Promise.resolve(thenable);
p3.then(function(v) {
    console.log(v); // 輸出"Resolving"
}, function(e) {
    // 不會(huì)被調(diào)用
});

6. Promise.reject()

Promise.reject(reason)方法也會(huì)返回一個(gè)新的Promise實(shí)例,該實(shí)例的狀態(tài)為rejected。

Promise.reject("Testing static reject").then(function(reason) {
    // 未被調(diào)用
}, function(reason) {
    console.log(reason); // "Testing static reject"
});

Promise.reject(new Error("fail")).then(function(result) {
    // 未被調(diào)用
}, function(error) {
    console.log(error); // stacktrace
});

// 注意:無論P(yáng)romise.reject的參數(shù)是什么,只要變成了rejected或者resolved。都會(huì)執(zhí)行then里面的reject函數(shù)。
7. Promise.all(iterable)

Promise.all(iterable) 方法返回一個(gè) Promise 實(shí)例,此實(shí)例在 iterable 參數(shù)內(nèi)所有的 promise 都“完成(resolved)”或參數(shù)中不包含 promise 時(shí)回調(diào)完成(resolve);如果參數(shù)中 promise 有一個(gè)失敗(rejected),此實(shí)例回調(diào)失敗(reject),失敗原因的是第一個(gè)失敗 promise 的結(jié)果。

var p1 = Promise.resolve(3);
var p2 = 1337;
var p3 = new Promise((resolve, reject) => {
    setTimeout(resolve, 100, "foo");
}); 

Promise.all([p1, p2, p3]).then(values => { 
    console.log(values); // [3, 1337, "foo"] 
});

Promise.race(iterable)

race 函數(shù)返回一個(gè) Promise,它將與第一個(gè)傳遞的 promise 相同的完成方式被完成。它可以是完成( resolves),也可以是失敗(rejects),這要取決于第一個(gè)完成的方式是兩個(gè)中的哪個(gè)。
如果傳的迭代是空的,則返回的 promise 將永遠(yuǎn)等待。
如果迭代包含一個(gè)或多個(gè)非承諾值和/或已解決/拒絕的承諾,則 Promise.race 將解析為迭代中找到的第一個(gè)值。

var p1 = new Promise(function(resolve, reject) { 
    setTimeout(resolve, 500, "one"); 
});
var p2 = new Promise(function(resolve, reject) { 
    setTimeout(resolve, 100, "two"); 
});

Promise.race([p1, p2]).then(function(value) {
  console.log(value); // "two"
  // 兩個(gè)都完成,但 p2 更快
});

var p3 = new Promise(function(resolve, reject) { 
    setTimeout(resolve, 100, "three");
});
var p4 = new Promise(function(resolve, reject) { 
    setTimeout(reject, 500, "four"); 
});

Promise.race([p3, p4]).then(function(value) {
  console.log(value); // "three"
  // p3 更快,所以它完成了              
}, function(reason) {
  // 未被調(diào)用
});

var p5 = new Promise(function(resolve, reject) { 
    setTimeout(resolve, 500, "five"); 
});
var p6 = new Promise(function(resolve, reject) { 
    setTimeout(reject, 100, "six");
});

Promise.race([p5, p6]).then(function(value) {
  // 未被調(diào)用             
}, function(reason) {
  console.log(reason); // "six"
  // p6 更快,所以它失敗了
});
五、Promise只能進(jìn)行異步操作?
Promise在規(guī)范上規(guī)定Promise只能使用異步調(diào)用方式。
```
// 可以看出promise是 一個(gè)異步函數(shù)  
var promise = new Promise(function(resolve) {
    console.log("inner promise");                // 1 
    resolve(42);
});
promise.then(function(value) {
    console.log(value);                          // 3 
});
console.log("outer promise");                    // 2
```
why?

因?yàn)橥秸{(diào)用和異步調(diào)用同時(shí)存在容易導(dǎo)致一些混亂。舉個(gè)類似的例子。

function onReady(fn) {
    var readyState = document.readyState;
    if (readyState === "interactive" || readyState === "complete") {  // 已加載,文檔與用戶可以開始交互 || 載入完成
        fn();
    } else {
        window.addEventListener("DOMContentLoaded", fn); 
    }
}
onReady(function () {
    console.log("DOM fully loaded and parsed");
});
console.log("==Starting==");

如上js函數(shù)會(huì)根據(jù)執(zhí)行時(shí)DOM是否已經(jīng)裝載完畢來決定是對(duì)回調(diào)函數(shù)進(jìn)行同步調(diào)用還是異步調(diào)用。因此,如果這段代碼在源文件中出現(xiàn)的位置不同,在控制臺(tái)上打印的log消息順序也會(huì)不同。為了解決這個(gè)問題,我們可以選擇統(tǒng)一使用異步調(diào)用的方式。

function onReadyPromise() {
    return new Promise(function (resolve, reject) {
        var readyState = document.readyState;
        if (readyState === "interactive" || readyState === "complete") {   // 已加載,文檔與用戶可以開始交互 || 載入完成
            resolve(); 
        } else {
            window.addEventListener("DOMContentLoaded", resolve); 
        }
    }); 
}
onReadyPromise().then(function () { 
    console.log("DOM fully loaded and parsed");
}); 
console.log("==Starting==");

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/102416.html

相關(guān)文章

  • JS-Promise

    摘要:對(duì)象表示異步操作的最終完成或失敗及其結(jié)果值。狀態(tài)初始狀態(tài),未完成或拒絕。返回使用給定值解析的對(duì)象。根據(jù)的屬性選擇返回對(duì)應(yīng)的狀態(tài)簡(jiǎn)簡(jiǎn)單單的敘述下常用的幾個(gè)屬性,有不對(duì)的地方請(qǐng)指教昨天看了一篇文章,還是挺有啟發(fā)的。。。。。 Promise The Promise object represents the eventual completion (or failure) of an asy...

    widuu 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<