// syntax,executor 是生產程式碼,最終會產生結果,傳到 promise,promise 物件有 2 個內部屬性,
// state 描述 promise 狀態,一開始 pedding => fullfilled or rejected
// result 任意值,一開始 undefined => value or error
let promise = new Promise(function(resolve, reject) {
// executor (生产者代码,"singer")
});
// 會自動呼叫 executor,executor 會接收 resolve、reject 2 個參數。
let promise = new Promise(function(resolve, reject) {
// the function is executed automatically when the promise is constructed
// after 1 second signal that the job is done with the result "done"
setTimeout(() => resolve("done"), 1000);
});
let promise = new Promise(function(resolve, reject) {
// after 1 second signal that the job is finished with an error
setTimeout(() => reject(new Error("Whoops!")), 1000);
});
// executor 只會有一個結果,另一個結果會被忽略。
let promise = new Promise(function(resolve, reject) {
resolve("done");
reject(new Error("…")); // 被忽略
setTimeout(() => resolve("…")); // 被忽略
});
// 可以使用任何類型的參數帶入 reject,但建議使用 Error 物件
// 通常 executor 會執行一些異步程式,這時需要一些時間才能得到結果。我們可以立即返回結果,當任務
// 已經完成。
let promise = new Promise(function(resolve, reject) {
// not taking our time to do the job
resolve(123); // immediately give the result: 123
});
// promise 的內建屬性 state and result,不能從消費程式碼取得,但可以透過
// .then/.catch/.finally 等方法取得
Consumers: then, catch, finally
消費程式碼可以得知生產結果,透過 .then, .catch and .finally等方法。
then
// syntax,成功時執行第 1 個參數,失敗時執行第 2 個參數
promise.then(
function(result) { /* handle a successful result */ },
function(error) { /* handle an error */ }
);
// 成功
let promise = new Promise(function(resolve, reject) {
setTimeout(() => resolve("done!"), 1000);
});
// resolve runs the first function in .then
promise.then(
result => alert(result), // shows "done!" after 1 second
error => alert(error) // doesn't run
);
// 失敗
let promise = new Promise(function(resolve, reject) {
setTimeout(() => reject(new Error("Whoops!")), 1000);
});
// reject runs the second function in .then
promise.then(
result => alert(result), // doesn't run
error => alert(error) // shows "Error: Whoops!" after 1 second
);
// 只返回成功結果
let promise = new Promise(resolve => {
setTimeout(() => resolve("done!"), 1000);
});
promise.then(alert); // shows "done!" after 1 second
catch
// 只返回失敗結果,可以用 .then(null, errorHandlingFunction) 或 .catch(errorHandlingFunction)
// .catch(f) 是 .then(null, f) 的簡寫
let promise = new Promise((resolve, reject) => {
setTimeout(() => reject(new Error("Whoops!")), 1000);
});
// .catch(f) is the same as promise.then(null, f)
promise.catch(alert); // shows "Error: Whoops!" after 1 second
finally
// 就像 try {...} catch {...} 有 finally,promise 也有 finally
// .finally(f) 很像 .then(f, f),當 promise 完成他會被執行無論成功或失敗。
// finally 適合使用在清空記憶體
new Promise((resolve, reject) => {
/* do something that takes time, and then call resolve/reject */
})
// runs when the promise is settled, doesn't matter successfully or not
.finally(() => stop loading indicator)
.then(result => show result, err => show error)
// .finally(f) 跟 .then(f, f) 的差別
// 1. finally 沒有參數
// 2. finally 傳遞 result 參數
// 成功
new Promise((resolve, reject) => {
setTimeout(() => resolve("result"), 2000)
})
.finally(() => alert("Promise ready"))
.then(result => alert(result)); // <-- .then handles the result
// 失敗
new Promise((resolve, reject) => {
throw new Error("error");
})
.finally(() => alert("Promise ready"))
.catch(err => alert(err)); // <-- .catch handles the error object
// 3. .finally(f) 比 .then(f, f) 簡潔
// 當 promise 執行完畢結果會立即回傳
// an immediately resolved promise
let promise = new Promise(resolve => resolve("done!"));
promise.then(alert); // done! (shows up right now)
Example: loadScript
function loadScript(src, callback) {
let script = document.createElement('script');
script.src = src;
script.onload = () => callback(null, script);
script.onerror = () => callback(new Error(`Script load error for ${src}`));
document.head.append(script);
}
// 重新改寫
function loadScript(src) {
return new Promise(function(resolve, reject) {
let script = document.createElement('script');
script.src = src;
script.onload = () => resolve(script);
script.onerror = () => reject(new Error(`Script load error for ${src}`));
document.head.append(script);
});
}
// 使用
let promise = loadScript("https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js");
promise.then(
script => alert(`${script.src} is loaded!`),
error => alert(`Error: ${error.message}`)
);
promise.then(script => alert('One more handler to do something else!'));
Promises
Callbacks
Promises allow us to do things in the natural order. First, we run loadScript(script), and .then we write what to do with the result.
We must have a callback function at our disposal when calling loadScript(script, callback). In other words, we must know what to do with the result beforeloadScript is called.
There can be only one callback.
We can call .then on a Promise as many times as we want. Each time, we’re adding a new “fan”, a new subscribing function, to the “subscription list”. More about this in the next chapter: .