function myAsyncFunction(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();
})
}
Promise.all()
静态方法接受一个 Promise 可迭代对象作为输入,并返回一个 Promise。当所有输入的 Promise 都被兑现时,返回的 Promise 也将被兑现(即使传入的是一个空的可迭代对象),并返回一个包含所有兑现值的数组。如果输入的任何 Promise 被拒绝,则返回的 Promise 将被拒绝,并带有第一个被拒绝的原因。
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo')
});
Promise.all([promise1,promise2,promise3]).then((value) => {
console.log(value)
})
状态为fulfilled 和rejected
如果 Promise.all
失败,也是一样的:
只有当传递给 Promise.all
的 iterable
为空时,Promise.all
才会同步解
const p = Promise.all([]);// 将会立即解决
const p2 = Promise.all([1377, 'hi']);// 非promise值将被忽略,但求值是异步进行的
console.log(p);
console.log(p2);
setTimeout(() => {
console.log("队列现在为空");
console.log(p2)
})
function promptForDishChoice() {
return new Promise((resolve,reject) => {
const dialog = document.createElement("dialog");
dialog.innerHTML = `
`;
dialog.addEventListener("close",() => {
if(dialog.returnValue === "ok") {
resolve(dialog.querySelector("select").value)
} else {
reject(new Error("user canceled dialog"))
}
});
document.body.appendChild(dialog);
dialog.showModal();
})
}
async function fetchPrices() {
const response = await promptForDishChoice();
console.log(response,'response')
// return await response.json();
}
fetchPrices()
promise.all()
async function getPrice () {
const [choice, prices] = await Promise.all([
promptForDishChoice(),
fetchPrice(),
]);
return prices[choice]
}
Promise.all
在任意一个传入的 promise 失败时返回失败。例如,如果你传入四个超时后解决的 promise 和一个立即拒绝的 promise,那么 Promise.all
将立即被拒绝。
const p1 = new Promise((resolve, reject) => {
setTimeout(() => resolve("一"),1000);
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => resolve("二"),2000);
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => resolve("三"),3000);
})
const p4 = new Promise((resolve, reject) => {
setTimeout(() => resolve("四"),4000);
})
const p5 = new Promise((resolve, reject) => {
reject(new Error("拒绝"))
})
// 使用.catch
Promise.all([p1,p2,p3,p4,p5])
.then((values) => {
console.log(values)
})
.catch((error) => {
console.log(error.message)
})
通过处理可能的拒绝,可以更改此行为:
Promise.allSettled()
静态方法将一个 Promise 可迭代对象作为输入,并返回一个单独的 Promise,当所有输入的 Promise都已敲定时(包括传入空的可迭代对象时),返回的 Promise 将被兑现,并带有描述每个 Promise结果的对象数组。
const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => {
setTimeout(reject, 100, 'foo')
})
const promises = [promise1, promise2];
Promise.allSettled(promises).then((results) => {
results.forEach((result) => {
console.log(result.status)
})
})
Promise.any()
静态方法将一个 Promise 可迭代对象作为输入,并返回一个 Promise。当输入的任何一个 Promise 兑现时,这个返回的 Promise 将会兑现,并返回第一个兑现的值。当所有输入 Promise 都被拒绝(包括传递了空的可迭代对象)时,它会以一个包含拒绝原因数组的 AggregateError 拒绝。
Promise.any()
会以第一个兑现的 Promise 来兑现,即使有 Promise 先被拒绝。这与 Promise.race() 不同,后者会使用第一个敲定的 Promise 来兑现或拒绝。
如果没有 Promise 被兑现,Promise.any()
将使用 AggregateError 进行拒绝。
在这个例子,我们有一个获取图片并返回 blob 的函数,我们使用 Promise.any()
来获取一些图片并显示第一张可用的图片(即最先解决的那个 promise)。
async function fetchAndDecode(url, description) {
const res = await fetch(url);
if(!res.ok) {
throw new Error(`HTTP错误!状态码:${res.status}`)
}
const data = await res.blob();
return [data, description]
}
const coffee = fetchAndDecode("coffee.jpg","Coffee");
const tea = fetchAndDecode('tea.jpg','Tea');
Promise.any([coffee, tea])
.then(([blob, description]) => {
const objectURL = URL.createObjectURL(blob);
const image = document.createElement("img");
image.src = objectURL;
image.alt = description;
document.body.appendChild(image)
})
.catch((e) => {
console.error(e)
})
Promise 实例的 catch()
方法用于注册一个在 promise 被拒绝时调用的函数。它会立即返回一个等效的 Promise 对象,这可以允许你链式调用其他 promise 的方法。此方法是 Promise.prototype.then(undefined, onRejected) 的一种简写形式。
在链式调用中使用 catch() 方法
在异步函数内部抛出的错误会像未捕获的错误一样:
如果 Promise 已兑现,catch() 不会被调用
Promise 实例的 finally()
方法用于注册一个在 promise 敲定(兑现或拒绝)时调用的函数。它会立即返回一个等效的 Promise 对象,这可以允许你链式调用其他 promise 方法。
这可以让你避免在 promise 的 then() 和 catch() 处理器中重复编写代码。
使用 finally()
let isLoading = true;
fetch(myRequest)
.then((response) => {
const contentType = response.headers.get("content-type");
if(contentType && contentType.includes("application/json")) {
return response.json()
}
throw new TypeError('ERROR ERROR')
}).then((json) => {
}).catch((error) => {
console.error(error)
}).finally(() => {
isLoading = false
})
Promise.race()
静态方法接受一个 promise 可迭代对象作为输入,并返回一个 Promise。这个返回的 promise 会随着第一个 promise 的敲定而敲定。
这个例子展示了如何使用 Promise.race()
来比较多个使用 setTimeout() 实现的计时器。计时时间最短的计时器总是赢得竞态,并成为返回的 promise 状态。
以下示例演示了 Promise.race
的异步性。与其他 promise 并发方法不同,Promise.race
总是异步的:即使 iterable
为空,它也永远不会同步地完成。
// 传入一个已经解决的Promise数组,以尽快触发Promise.race
const resolvedPromiseArray = [Promise.resolve(33), Promise.resolve(44)];
const p = Promise.race(resolvedPromiseArray);
// 立即打印p的值
console.log(p);
// 使用setTimeout.我们可以在堆栈为空后执行代码
setTimeout(() => {
console.log("堆栈现在为空");
console.log(p)
})
一个空的可迭代对象会导致返回的 Promise 一直处于待定状态:
const foreverPendingPromise = Promise.race([]);
console.log(foreverPendingPromise);
setTimeout(() => {
console.log("堆栈现在为空");
console.log(foreverPendingPromise)
})
如果可迭代对象包含一个或多个非 Promise 值和/或一个已经敲定的 Promise,则 Promise.race
会以数组中找到的第一个这样的值敲定:
const foreverPendingPromise = Promise.race([]);
const alreadyFulfilledProm = Promise.resolve(100);
const arr = [foreverPendingPromise,alreadyFulfilledProm,"非Promise值"];
const arr2 = [foreverPendingPromise,'非Promise值',Promise.resolve(100)]
const p = Promise.race(arr);
const p2 = Promise.race(arr2);
console.log(p);
console.log(p2);
setTimeout(() => {
console.log("堆栈现在为空");
console.log(p);
console.log(p2);
})
你可以使用一个定时器来与一个可能持续很长时间的请求进行竞争,以便超出时间限制时,返回的 Promise 自动拒绝。
const data = Promise.race([
fetch('/api'),
new Promise((resolve, reject) => {
// 5秒后拒绝
setTimeout(() => reject(new Error('请求超时')),5000)
})
])
.then((res) => res.json())
.catch((err) => displayError(err))
const p1 = new Promise((res) => setTimeout(() => res(100), 100));
const p2 = new Promise((res) => setTimeout(() => res(200), 200));
const p3 = new Promise((res, rej) => setTimeout(() => rej(300), 100));
function promiseState(promise) {
const pendingState = { status: "待定" };
return Promise.race([promise, pendingState]).then(
(value) => (value === pendingState ? value : { status: "已兑现", value }),
(reason) => ({ status: "已拒绝", reason }),
);
}
async function getStates() {
console.log(await promiseState(p1));
console.log(await promiseState(p2));
console.log(await promiseState(p3));
}
console.log("开始状态:");
getStates();
setTimeout(() => {
console.log("等待 100ms 后:");
getStates();
}, 100);
Promise.race
方法以可迭代对象中第一个敲定的 Promise 作为敲定值。
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, "一");
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(reject, 100, "二");
});
Promise.race([promise1, promise2])
.then((value) => {
console.log("成功,值为:", value);
})
.catch((reason) => {
// 只有 promise1 成功兑现,但 promise2 更快
console.error("失败,原因为:", reason);
});
// 失败,原因为:二
Promise.any 方法以可迭代对象中第一个被兑现的 Promise 作为兑现值。
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, "一");
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(reject, 100, "二");
});
Promise.any([promise1, promise2])
.then((value) => {
// 只有 promise1 成功兑现,即使 promise2 更快敲定
console.log("成功,值为:", value);
})
.catch((reason) => {
console.error("失败,原因为:", reason);
});
// 成功,值为:一
Promise.reject()
静态方法返回一个已拒绝(rejected)的 Promise
对象,拒绝原因为给定的参数。
function resolved(result) {
console.log('Resolved')
}
function rejected(result) {
console.error(result)
}
Promise.reject(new Error('fail'))
.then(resolved,rejected)
Promise.reject
静态方法返回一个被拒绝的 Promise
对象。
该函数可以用 resolve
和 reject
回调函数作为参数进行调用。Promise.reject()
实际上相当于 new Promise((resolve, reject) => reject(reason))
的简写形式。
Promise.reject(new Error("失败"))
.then(
() => {
// 不会被调用
},
(error) => {
console.error(error)
}
)
与 Promise.resolve 不同,Promise.reject
方法不会重用已存在的 Promise
实例。它始终返回一个新的 Promise
实例,该实例封装了拒绝的原因(reason
)。
Promise.resolve()
方法会重用已存在的 Promise
实例。如果它正在解决一个原生的 Promise,它将返回同一 Promise 实例,而不会创建一个封装对象。
嵌套的 thenable 对象将被“深度展平”为单个 Promise 对象
const thenable = {
then(onFulfilled,onRejected) {
onFulfilled({
// 该thenable对象将兑现为另外一个thenable对象
then(onFulfilled,onRejected) {
onFulfilled(42)
}
})
}
}
Promise.resolve(thenable).then((v) => {
console.log(v);// 12
})
警告: 不要在一个解决为自身的 thenable 对象上调用 Promise.resolve()
。这将导致无限递归,因为它试图展平一个无限嵌套的 Promise。
const thenable = {
then(onFulfilled, onRejected) {
onFulfilled(thenable);
},
};
Promise.resolve(thenable); // 将会导致无限递归。
class NotPromise {
constructor(executor) {
executor(
(value) => console.log("已解决",value),
(reason) => console.log("已拒绝",reason)
)
}
}
Promise.resolve.call(NotPromise, 'foo');// 输出 “已解决foo”
const thenable = {
then(onFulfilled, onRejected) {
onFulfilled({
// 该 thenable 对象将兑现为另一个 thenable 对象
then(onFulfilled, onRejected) {
onFulfilled(42);
},
});
},
};
Promise.resolve.call(NotPromise, thenable); // 输出 "已兑现 { then: [Function: then] }"
onFulfilled
可选
一个在此 Promise 对象被兑现时异步执行的函数。它的返回值将成为 then()
返回的 Promise 对象的兑现值。此函数被调用时将传入以下参数:
onRejected
可选
一个在此 Promise 对象被拒绝时异步执行的函数。它的返回值将成为 catch()
返回的 Promise 对象的兑现值。此函数被调用时将传入以下参数:
如果 onFulfilled
返回一个 Promise,那么 then
的返回值将根据该 Promise 的最终状态被兑现或被拒绝。
你可以使用链式调用,在一个函数上实现基于 Promise 的 API,在另一个函数之上。
参考原文:(以上都是来自官方文档,此文档仅供学习参考笔记记录)
Promise() 构造函数 - JavaScript | MDN (mozilla.org)