Appearance
Promise async await
Promise
未处理的 Error
在浏览器中,我们可以使用 unhandledrejection 事件捕获它:
plain
window.addEventListener('unhandledrejection', function(event) {
// the event object has two special properties:
alert(event.promise); // [object Promise] - the promise that generated the error
alert(event.reason); // Error: Whoops! - the unhandled error object
});
new Promise(function() {
throw new Error("Whoops!");
}); // no catch to handle the error“error-first callback” 风格
javascript
loadScript('/my/script.js', function(error, script) {
if (error) {
// handle error
} else {
// 成功加载脚本
}
});
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);
}promise 对象有内部属性:
state—— 最初是 “pending”,然后被改为 “fulfilled” 或 “rejected”,result—— 一个任意值,最初是undefined。
reject/throw a error
从技术上来说,我们可以使用任何类型的参数来调用 reject(就像 resolve)。但建议在 reject(或从它们中继承)中使用 Error 对象。 错误原因就会显示出来。
Promise chain
因为 promise.then 返回了一个 promise,所以我们可以用它调用下一个 .then。
当控制函数返回一个值时,它会变成当前 promise 的 result,所以会用它调用下一个 .then
javascript
new Promise(function(resolve, reject) {
setTimeout(() => resolve(1), 1000); // (*)
}).then(function(result) { // (**)
alert(result); // 1
return result * 2;
}).then(function(result) { // (***)
alert(result); // 2
return result * 2;
}).then(function(result) {
alert(result); // 4
return result * 2;
});返回thenable对象
.then 可以返回任意的 “thenable” 对象,并且会被当做一个 promise 来对待javascript
class Thenable {
constructor(num) {
this.num = num;
}
then(resolve, reject) {
alert(resolve); // function() { native code }
// 1 秒后用 this.num*2 来 resolve
setTimeout(() => resolve(this.num * 2), 1000); // (**)
}
}
new Promise(resolve => resolve(1))
.then(result => {
return new Thenable(result); // (*)
})
.then(alert); // 1000 ms 后显示 2then方法中返回 promises 允许我们建立异步动作链。
错误处理
当一个 promise reject 时,代码控制流程跳到链中最近的 rejection 处理程序。这在实践中非常方便。
隐式catch
javascript
new Promise(function(resolve, reject) {
throw new Error("Whoops!");
}).catch(alert); // Error: Whoops!
=== 等于下面的
new Promise(function(resolve, reject) {
reject(new Error("Whoops!"));
}).catch(alert); // Error: Whoops!re-throw
如果我们在 .catch 里面 throw,那么控制流程将转到。
如果我们处理错误并正常结束,那么它将继续执行最接近的 .then 成功处理程序。
Promise.resolve
根据给定的 value 值返回 resolved promise。
等价于:
plain
let promise = new Promise(resolve => resolve(value));如何接口的一致性 可以使用loadCached(url).then这样子
确保接口返回都返回Promise
javascript
function loadCached(url) {
let cache = loadCached.cache || (loadCached.cache = new Map());
if (cache.has(url)) {
return Promise.resolve(cache.get(url)); // (*)
}
return fetch(url)
.then(response => response.text())
.then(text => {
cache[url] = text;
return text;
});
}Promise.all
`Promise.all``[1, 2, 3]`javascript
Promise.all([
new Promise((resolve, reject) => setTimeout(() => resolve(1), 3000)), // 1
new Promise((resolve, reject) => setTimeout(() => resolve(2), 2000)), // 2
new Promise((resolve, reject) => setTimeout(() => resolve(3), 1000)) // 3
]).then(alert);如果任何 promise 为 rejected,Promise.all 就会立即以 error reject。
如何避免fetch请求中一个错误导致Promise.all失败
根据 promise 的工作原理,只要 .then/catch 处理器返回值(无论是 error 对象或其他内容),执行流程就会“正常”进行
javascript
Promise.all(
urls.map(url => fetch(url).catch(err => err))
)await-to-js -
await-to-js
https://www.npmjs.com/package/await-to-js
javascript
import to from 'await-to-js';
// If you use CommonJS (i.e NodeJS environment), it should be:
// const to = require('await-to-js').default;
async function asyncTaskWithCb(cb) {
let err, user, savedTask, notification;
[ err, user ] = await to(UserModel.findById(1));
if(!user) return cb('No user found');
[ err, savedTask ] = await to(TaskModel({userId: user.id, name: 'Demo Task'}));
if(err) return cb('Error occurred while saving task');
if(user.notificationsEnabled) {
[ err ] = await to(NotificationService.sendNotification(user.id, 'Task Created'));
if(err) return cb('Error while sending notification');
}
if(savedTask.assignedUser.id !== user.id) {
[ err, notification ] = await to(NotificationService.sendNotification(savedTask.assignedUser.id, 'Task was created for you'));
if(err) return cb('Error while sending notification');
}
cb(null, savedTask);
}更新: 2019-09-12 14:23:36
原文: https://www.yuque.com/u3641/dxlfpu/ikzs1e