上周讲了promise用法,这周咱们讲一下promise实战中可能出现得一些易错点,若是对promise基础不是很了解能够去看个人上一篇文章 promise入门数组
remotedb.allDocs({
include_docs: true,
attachments: true
}).then(function (result) {
var docs = result.rows;
docs.forEach(function(element) {
localdb.put(element.doc).then(function(response) {
alert("Pulled doc with id " + element.doc._id + " and added to local db.");
}).catch(function (err) {
if (err.status == 409) {
localdb.get(element.doc._id).then(function (resp) {
localdb.remove(resp._id, resp._rev).then(function (resp) {}
}
})
复制代码
promise得新特性之一就是解决回调地狱问题,因此咱们能够换个更优雅得写法达到上段代码的效果promise
remotedb.allDocs(...).then(function (resultOfAllDocs) {
return localdb.put(...);
}).then(function (resultOfPut) {
return localdb.get(...);
}).then(function (resultOfGet) {
return localdb.put(...);
}).catch(function (err) {
console.log(err);
});
复制代码
######常见问题二 : 用了 promises
后怎么用 forEach
?bash
/ I want to remove() all docs
db.allDocs({include_docs: true}).then(function (result) {
result.rows.forEach(function (row) {
db.remove(row.doc);
});
}).then(function () {
// I naively believe all docs have been removed() now!
});
复制代码
这份代码有什么问题?问题在于第一个then
函数实际上返回的是 undefined
(入门篇讲过咱们须要手动return
),这意味着第二个方法不会等待全部 documents 都执行 db.remove()
方法(由于后一个then
接收到的undefind
并无相似于promise
实例状态ejected/fullfilled
)。因此他不会等待任何事情,而且可能会在任意数量的文档被删除后执行! 这里咱们须要用 Promise.all()
异步
db.allDocs({include_docs: true}).then(function (result) {
return Promise.all(result.rows.map(function (row) {
return db.remove(row.doc);
}));
}).then(function (arrayOfResults) {
// All docs have really been removed() now!
});
复制代码
上面的代码是什么意思呢?大致来讲,Promise.all()
会以一个 promises
数组为输入,而且返回一个新的 promise
。这个新的 promise
会在数组中全部的 promises
都成功返回后才返回。一旦数组中的 promise
任意一个返回错误,Promise.all()
也会返回错误,他是异步版的 for
循环。函数
咱们在使用程序的时候,不免会出现问题,若是不适用catch
找起问题来会特别麻烦ui
somePromise().then(function () {
return anotherPromise();
}).then(function () {
return yetAnotherPromise();
}).catch(
err=>{
thorw new Error(err)
});
复制代码
没有return
返回新的promise
就会默认返回一个undefind
,这就是反作用spa
somePromise().then(function () {
someOtherPromise();
}).then(function () {
// Gee, I hope someOtherPromise() has resolved!
// Spoiler alert: it hasn't. }); 复制代码
每个 promise
都会提供给你一个 then()
函数 (或是 catch()
,实际上只是 then(null, ...)
的语法糖)。当咱们在 then() 函数内部时:调试
somePromise().then(function () {
// 这里能够作什么???
});
复制代码
咱们能够在这里作三件事情code
return
另外一个promise
return
一个同步的值 (或者undefined
)throw
一个同步异常咱们来看一下这三种事情blog
getUserByName('nolan').then(function (user) {
return getUserAccountById(user.id);
}).then(function (userAccount) {
// I got a user account!
});
复制代码
注意到我是 return
第二个 promise,这个 return
很是重要。若是我没有写 return
,getUserAccountById()
就会成为一个反作用,而且下一个函数将会接收到 undefined
而非新的 promise
。
undefined
一般是错误的,可是返回一个同步值其实是将同步代码包裹为 promise
风格代码的一种很是赞的手段。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!
});
复制代码
是否是很赞?第二个函数不须要关心 userAccount
是从同步方法仍是异步方法中获取的,而且第一个函数能够很是自由的返回一个同步或者异步值。
不幸的是,有一个不便的现实是在 JavaScript 中无返回值函数在技术上是返回 undefined
,这就意味着当你本意是返回某些值时,你很容易会不经意间引入反作用。
出于这个缘由,我我的养成了在 then()
函数内部 永远返回或抛出 的习惯。我建议你也这样作。
####进阶错误 ######不知道 Promise.resolve()/Promise.reject(); 咱们会常常这么使用promise
new Promise(function (resolve, reject) {
resolve(someSynchronousValue);
}).then(/* ... */);
复制代码
使用 Promise.resolve()
会更加简洁
Promise.resolve(someSynchronousValue).then(/* ... */);
复制代码
咱们应该在全部 promise 形式的 API 接口中这样使用它
function somePromiseAPI() {
return Promise.resolve().then(function () {
doSomethingThatMayThrow();
return 'foo';
}).then(/* ... */);
}
复制代码
任何有可能 throw 同步异常的代码都是一个后续会致使几乎没法调试异常的潜在因素。可是若是你将全部代码都使用 Promise.resolve() 封装,那么你老是能够在以后使用 catch() 来捕获它。 相似的,还有 Promise.reject() 你能够用来返回一个马上返回失败的 promise。
Promise.reject(new Error('some awful error'));
复制代码
Promise.resolve('foo').then(
Promise.resolve('bar')
).then(function (result) {
console.log(result); //foo
});
复制代码
之因此会打印foo而不是bar,是由于咱们 Promise.resolve('bar')
这段代码有问题,这段代码返回的是一个promise
,但咱们并无return
Promise.resolve('foo').then(function () {
return Promise.resolve('bar');
}).then(function (result) {
console.log(result);
});
复制代码
固然promise还有一些高级的用法,你们能够去读一下 promise,个人实例代码所有是这篇文章的,做者是一个外国大牛,有兴趣的能够去看一下