iT邦幫忙

2021 iThome 鐵人賽

DAY 27
0
Modern Web

初學者跪著學JavaScript系列 第 27

初學者跪著學JavaScript Day27 : 渣男給不完的promise

一日客語:中文:鳳梨 客語:vong(三聲)李(黃梨)

介紹promise

簡化非同步程式設計的一項語言

mdn:
new Promise ( /* executor */ function(resolve, reject) { ... } );

  1. Promise 是建構子需要大寫,和new 創建出一個物件

  2. callback function (第一個參數:resolve、第二個參數:reject )

  3. resolve、reject 參數是各自的 function

  4. 新創建的物件會是非同步計算結果,裡面會有 [[PromiseState]] 表示目前狀態

const promise = new Promise((resolve, reject) => {});

//也可以自行定義
const promise = new Promise((sucessful, fail) => {});

此時PromiseState : ”pending"

物件剛建立會先處在 pending 狀態

promise 物件會有三種狀態:

  1. pending:未取得結果

  2. fulfilled:成功完成

  3. rejected:失敗


未使用resolve、rejected

他的 [[promiseState]] 會是 pending

const myPromise = new Promise((resolve, reject) => {
    console.log('執行了喔');
    // resolve('pmyPromise狀態改成rejected');
});


使用resolve

promise 被完成,會呼叫 resolve

當有執行 resolve function 他的狀態會變成"fulfilled"

const myPromise = new Promise((resolve, reject) => {
    console.log('執行了喔');
    resolve('pmyPromise狀態改成fulfilled');
});

看看瀏覽器顯示:

如下圖

使用reject

當有執行 reject function 他的狀態會變成 "rejected"

const myPromise = new Promise((resolve, reject) => {
    console.log('執行了喔');
    reject('pmyPromise狀態改成rejected');
});

看看瀏覽器顯示:

如下圖

或者中途錯誤

const promise = new Promise((resolve, reject) => {
    throw '糟糕要失敗了';
    console.log('開始');
});
promise.then(
    //resolve
    (resolve) => console.log(resolve + '耶成功'),
    //reject
    (reject) => console.log(reject + 'QQ被拒絕')
);//糟糕要失敗了QQ被拒絕

then語法

Promise具有then()方法,promise.then()

mdn:p.then(onFulfilled[, onRejected]);

then() 方法回傳一個 Promise 物件。

接收兩個引數: Promise 在成功及失敗情況時的回呼函式callback function。

第一個callback function,由resolve值傳入

第二個callback function,由reject值傳入

const promise = new Promise((resolve, reject) => {
    resolve('我是resolve');
});
promise.then(
    //resolve
    (resolve) => console.log(resolve + '耶成功'),
    //reject
    (reject) => console.log(reject + 'QQ被拒絕')
);
//我是resolve耶成功
const promise = new Promise((resolve, reject) => {
    reject('我是reject');
});
promise.then(
    //resolve
    (resolve) => console.log(resolve + '耶成功'),
    //reject
    (reject) => console.log(reject + 'QQ被拒絕')
);
//我是rejectQQ被拒絕

可以用另一種寫法:then()和catch()

const promise = new Promise((resolve, reject) => {
    reject('我是reject');
});
promise
    .then(
        //resolve
        (resolve) => console.log(resolve + '耶成功')
    )
    .catch(
        //reject
        (reject) => console.log(reject + 'QQ被拒絕')
    );

可以透過then把resolve/reject的值傳遞

let myPromise = new Promise((resolve, reject) => {
    resolve('我是resolve');
});
myPromise.then((result) => console.log('你是誰', result));
//你是誰 我是resolve

執行順序:發現 then 是最後才被印出

function funcA() {
    return new Promise(function (reslove, reject) {
        console.log('nini:你在哪裡');
        setTimeout(() => {
            reslove('渣男:我在家裡啊');
        }, 1000);
    });
}
funcA().then(function (x) {
    console.log(x);
});

console.log('這裡是外面');
console.log('這裡是外面');
console.log('這裡是外面');
console.log('這裡是外面');
//nini:你在哪裡
//這裡是外面
//這裡是外面
//這裡是外面
//這裡是外面
//渣男:我在家裡啊

因為funcA().then(function (x) { console.log(x); });
這個仍是非同步

求婚劇情

男主角給女主角一個promise,表示要求婚了,會有兩種狀況

1.結婚,表示求婚成功

2.不結,表示求婚失敗

當隨機數字是1,女主答覆嫁,非1,女主角不嫁

利用then()來看女方答覆,加上吃瓜民眾結論

yes:女主角答覆+'女主角說願意,求婚成功'

no: 女主角答覆+'女主角說不願意,求婚失敗'

呈現結果會是

1.不嫁 女主角說不願意,求婚失敗

2.嫁 女主角說願意,求婚成功

function woman() {
    let randomNumber = Math.random() * 3;
    let random = Math.floor(randomNumber);
    return new Promise(function (resolve, reject) {
        if (random === 1) {
            return resolve('嫁');
        } else {
            return reject('不嫁');
        }
    });
}
woman()
    .then((yes) => console.log(yes, '女主角說願意,求婚成功'))
    .catch((no) => console.log(no, '女主角說不願意,求婚失敗'));

chaining Promises

可以利用 chaining Promises做出有順序的非同步執行

fetch(url).then(1).then(2).catch()

最後一個catch()處理發生任何錯誤

每一個then()方法都會回傳一個新物件

let person = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('要不要和我再一起');
    }, 1000);
});
person.then((result) => {
//傳給then 一個promise且回傳一個新值
    console.log(result);
    return '願意';
});
//要不要和我再一起

當return '願意'

他的[[PromiseResult]]: "願意"

當沒有return

他的[[PromiseResult]]: "undefined"

第一個then的return可以傳給下一個then

let person = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('要不要跟我在一起啊nini');
    }, 3 * 100);
});

person
    .then((result) => {
        console.log(result);
        return 'niki';
    })
    .then((result) => {
        console.log(`${result}要不要跟我在一起啊`);
        return 'kiki';
    })
    .then((result) => {
        console.log(`${result}要不要跟我在一起啊`);
        return 'mimi';
    });
//要不要跟我在一起啊nini
//niki要不要跟我在一起啊
//kiki要不要跟我在一起啊

then回傳promise

講述渣男故事1:

不同人打給渣男例子

function funcA() {
    return new Promise(function (reslove, reject) {
        console.log('nini:你在哪裡');
        setTimeout(() => {
            reslove('渣男:我在家裡啊');
        }, 1000);
    });
}
function funcB() {
    return new Promise(function (reslove, reject) {
        console.log('niki:你在哪裡啊');
        setTimeout(() => {
            reslove('渣男:我在公司啊');
        }, 1000);
    });
}
function funcC() {
    return new Promise(function (reslove, reject) {
        console.log('kiki:你在哪裡啊');
        setTimeout(() => {
            reslove('渣男:我找朋友');
        }, 1000);
        return '沒有人發現我在外面';
    });
}
funcA()
    .then(function (x) {
        console.log(x);
        return funcB();
    })
    .then(function (y) {
        console.log(y);
        return funcC();
    })
    .then(function (z) {
        console.log(z);
    });

console.log('*********這裡是酒吧*************');
//nini:你在哪裡
//*********這裡是酒吧*************
//渣男:我在家裡啊
//niki:你在哪裡啊
//渣男:我在公司啊
//kiki:你在哪裡啊
//渣男:我找朋友

講述渣男故事2:

男主角有三位女朋友

理想結婚人選 1.nini 2.niki 3.kiki

nini 小姐求婚,
求婚成功:結婚
求婚失敗:和下一位niki小姐求婚

niki 小姐求婚
求婚成功:結婚
求婚失敗:和下一位kiki小姐求婚

kiki 小姐求婚
求婚成功:結婚
求婚失敗:沒人願意和他結婚。 幫他QQ

套路是同招數一直使用

function marry(name) {
    let randomNumber = Math.random() * 3;
    let random = Math.floor(randomNumber);
    return new Promise(function (resolve, reject) {
        if (random === 1) {
            reject(` ${name} :說願意`);
        } else {
            resolve(` ${name} :說不願意`);
        }
    });
}
marry('nini')
    .then((fail) => {
        console.log(`求婚結果1${fail}`);
        return marry('niki');
    }) 
    .then((fail) => {
        console.log(`求婚結果2${fail}`);
        return marry('kiki');
    })
    .then((fail) => {
        console.log(`求婚結果3${fail}`);
        return '沒人要跟我結婚';
    })
    .catch((success) => {
        console.log(`求婚成功` + success);
        return '終於有對象';
    });
    

大概會是這樣的結果


害怕遇到渣男嗎?快來搞懂promiseXD

JavaScript Promise 全介紹
Introduction to the JavaScript promise chaining
[JS] Promise 的使用
JavaScript大全第七版


上一篇
初學者跪著學JavaScript Day26 : 認識生成器,chris不生氣
下一篇
初學者跪著學JavaScript Day28 : 學迭代,學習不等待
系列文
初學者跪著學JavaScript30

2 則留言

0
Hooo
iT邦新手 5 級 ‧ 2021-10-12 20:49:40

渣男舉例配 promise 好好懂 XDDD

wendy iT邦新手 5 級 ‧ 2021-10-13 09:28:13 檢舉

哈哈哈哈

0
南國ㄟ安迪
iT邦新手 5 級 ‧ 2021-10-12 20:54:35

收下我的膝蓋吧QQ...

剛剛用手機看笑好久

wendy iT邦新手 5 級 ‧ 2021-10-13 09:28:25 檢舉

邊寫邊笑

我要留言

立即登入留言