Reference:
參考資料1 參考資料2
Promise是什麼?
- Promise是一種特別的JavaScript object,它又包含了其他objects。
- 使用`.then()`來存取promise中的資料
function getFirstUser() {
return getUsers().then(function(users) {
return users[0].name;
});
}
function getFirstUser() {
return getUsers().then(function(users) {
return users[0].name;
}).catch(function(err) {
return {
name: 'default user'
};
});
}
- Promise是asynchronous的,不論現在就已經有資料或是將來才會有資料回傳。
- 在上面的code中getUsers()回傳一個Promise。使用ES2016,任何Promise都可以await。await等同於對Promise呼叫`.then( )`而且不需要callback。程式可以改寫如下:
async function getFirstUser() {
let users = await getUsers();
return users[0].name;
}
- await會讓method暫停執行,直到Promise的值是available。
- 而catch error的方式也可改用synchronous型式的try/catch:
async function getFirstUser() {
try {
let users = await getUsers();
return users[0].name;
} catch (err) {
return {
name: 'default user'
};
}
}
Awaiting multiple values
- 一般的使用下,一次只能await一個東西,下面這段code會依序執行await取得foo跟bar
let foo = await getFoo();
let bar = await getBar();
- 若我們想讓foo跟bar同時被設置,則可用下列code:
let [foo, bar] = await Promise.all([getFoo(), getBar()]);
- Promise.all( )是把一個array的Promises組合成單一的Promise,且array中的所有child promise都resolve後才算是真的resolve。
- Promise.all( )並沒有dispatch你帶進去的Promise,當[getFoo(), getBar()]執行時就已經在做dispatch的動作了。
- 還有另外一個有趣的方法可以讓async/await可以parallel執行如下:
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;
- 首先dispatch `getFoo`及`getBar`並將其回傳的Promise存在fooPromise及barPromise
- 這些動作正在進行中,沒有stop或delay發生
- 接著去await各個Promise
- 由於在await前就把所有async action都dispatch了,所以它們會同時執行
- foo跟bar
Handle callbacks
- 當你想在Promise的值available時呼叫callback,可用下列方法:
function getFirstUser(callback) {
return getUsers().then(function(user) {
return callback(null, users[0].name);
}).catch(function(err) {
return callback(err);
});
}
- 若在async function裡想要呼叫callback,則須把callback轉成會回傳Promise的function:
function callbackToPromise(method, ...args) {
return new Promise(function(resolve, reject) {
return method(...args, function(err, result) {
return err ? reject(err) : resolve(result);
});
});
}
async function getFirstUser() {
let users = await callbackToPromise(getUsers);
return users[0].name;
}
- 記得只要用到sync function就要去catch error做處理
Using side effects instead of returning
- 在Promise的then( )或catch( )能做三件事
- 回傳另一個Promise
- 這是一個常見的pattern用來組合Promise
getUserByName('nolan').then(function (user) {
return getUserAccountById(user.id);
}).then(function (userAccount) {
// I got a user account!
});
- 注意:那個return是重要的!若沒有加上return,則第二個Promise的function會收到undefined而非userAccount。
- 回傳一個synchronous的值
- 第二個Promise的 function並不在意參數是 sync或是async地取得
getUserByName('nolan').then(function (user) {
if (inMemoryCache[user.id]) {
return inMemoryCache[user.id]; // returning a synchronous value!
}
return getUserAccountById(user.id); // returning a promise!
}).then(function (userAccount) {
// I got a user account!
});
- Throw synchronous error
getUserByName('nolan').then(function (user) {
if (user.isLoggedOut()) {
throw new Error('user logged out!'); // throwing a synchronous error!
}
if (inMemoryCache[user.id]) {
return inMemoryCache[user.id]; // returning a synchronous value!
}
return getUserAccountById(user.id); // returning a promise!
}).then(function (userAccount) {
// I got a user account!
}).catch(function (err) {
// Boo, I got an error!
});
Promises fall through
- 你以為下列的code會印出bar但實際上會印出boo,這是因為若then( )裡面帶的不是function,則會被視為then(null),前一個Promise的結果會往下傳。
Promise.resolve('foo').then(Promise.resolve('bar')).then(function (result) {
console.log(result);
});
沒有留言:
張貼留言