html form callback,Promise异步编程模式总结初始化Promise对象统一错误处理PromisifyfromCallbackMongoose Promisify...
Promise是JavaScript中的一種異步編程范式, 一個(gè)Promise對(duì)象表示一個(gè)即將完成但還未完成的操作。 鑒于JavaScript中異步和回調(diào)的編程風(fēng)格, Promise模式可以有效地避免『Callback Hell』。
Promise 最初有q和bluebird等實(shí)現(xiàn),在ES2015(ES6)提出后Promise已經(jīng)進(jìn)入標(biāo)準(zhǔn),Node.js已經(jīng)開(kāi)始支持ES6的很多特性,包括Promise。
初始化
傳入一個(gè)回調(diào)函數(shù)即可初始化一個(gè)Promise對(duì)象padmin:
var padmin = new Promise(function(resolve, reject){
user.find({role: 'admin'}, function(err, admins){
if(err) reject(err);
else resolve(admins);
});
});
除此之外,ES6還給出4種常用的初始化方式,下列方法均返回一個(gè)Promise對(duì)象:
方法
說(shuō)明
Promise.all(iterable)
當(dāng)iterable(比如數(shù)組)中所有Promise都resolve時(shí),該P(yáng)romise resolve;iterable中任何一個(gè)被reject,則該P(yáng)romise被reject
Promise.race(iterable)
當(dāng)iterable中任意一個(gè)Promise被resolve或reject,該P(yáng)romise都會(huì)相應(yīng)地結(jié)束
Promise.reject(err)
直接返回一個(gè)被reject的Promise對(duì)象
Promise.reject(value)
直接返回一個(gè)被resolve的Promise對(duì)象
Promise對(duì)象
Promise對(duì)象padmin擁有兩個(gè)主要方法:
方法
說(shuō)明
Promise.prototype.catch(onRejected)
當(dāng)一個(gè)Promise被reject時(shí)調(diào)用onRejected
Promise.prototype.then(onFulfilled, onRejected)
當(dāng)一個(gè)Promise被resolve時(shí)調(diào)用onFulfilled,被reject時(shí)調(diào)用onRejected
上述兩個(gè)方法均返回一個(gè)Promise,這意味著.then和.catch可以鏈?zhǔn)綍?shū)寫(xiě)。例如:
padmin
.then(function(admins){
doSthWith(admins);
})
.catch(function(err){
console.error(err);
});
統(tǒng)一錯(cuò)誤處理
在任何一個(gè)then()回調(diào)中拋出的錯(cuò)誤都會(huì)被后面的catch()所截獲,以此可以做統(tǒng)一的錯(cuò)誤處理:
padmin
.then(function(admins){
if(admins === null) throw new Error('query admin error');
return admins.length;
})
.then(function(length){
if(length === 0) throw new Error('empty admin list');
console.log(length + ' admins in total.');
})
.catch(function(err){
console.error(err);
});
Promisify
Node.js的內(nèi)置庫(kù)以及大量的NPM工具都采用『Error-First Callback』風(fēng)格,例如:
fs.readFile('foo.txt', function(err, content){
if(err) console.error(err);
else console.log(content);
});
在Promise風(fēng)格的代碼中,通常會(huì)需要readFile返回一個(gè)Promise對(duì)象,于是常常會(huì)這樣包裝該API:
var readFileAsync = function(path){
return new Promise(function(resolve, reject){
fs.readFile(path, function(err, content){
if(err) reject(err);
else resolve(content);
});
});
}
readFileAsync('foo.txt')
.then(function(content){
console.log(content):
})
.catch(function(err){
console.error(err);
});
然而我們需要包裝fs模塊下的所有API 🙁 bluebird為此提供了有用的方法promisifyAll():
var fs = require("fs");
// 為fs的所有方法創(chuàng)建一個(gè)Promise包裝,命名為xxxAsync
Promise.promisifyAll(fs);
fs.readFileAsync("foo.txt").then(...).catch(...);
當(dāng)然也可以只包裝一個(gè)函數(shù):
var readFile = Promise.promisify(require("fs").readFile);
readFile("foo.txt").then(...).catch(...);
fromCallback
現(xiàn)在我們有了.promisify來(lái)把一個(gè)『Error-First Callback』風(fēng)格的API包裝為Promise風(fēng)格。 在某些特定情形下,可能每次使用都需要先進(jìn)行promisify,比如使用后即被銷(xiāo)毀的臨時(shí)對(duì)象。 例如從HTTP請(qǐng)求構(gòu)造的req對(duì)象每次請(qǐng)求都是新的:
function(req, res, next){
User.find({name: req.body.name})
.then(function(user) {
var login = Promise.promisify(req.login);
return login.call(req, user);
})
.catch(next);
}
這時(shí)可以用Promise.fromCallback方法,直接由『Error-First Callback』調(diào)用生成Promise對(duì)象,而不需要生成Promise風(fēng)格的方法。
function(req, res, next){
User.find({name: req.body.name})
.then(function(user) {
return BPromise.fromCallback(cb => req.login(user, cb));
})
.catch(next);
}
Mongoose Promisify
mongoose是MongoDB在JavaScript下的適配器(類(lèi)似ORM),提供了模型驗(yàn)證、數(shù)據(jù)轉(zhuǎn)換、業(yè)務(wù)邏輯鉤子、查詢(xún)鉤子等對(duì)象建模工具。 mongoose有些API(如.exec())會(huì)返回內(nèi)置的Promise,我們可以用一個(gè)更強(qiáng)的Promise來(lái)替代它:
var BPromise = require('bluebird');
mongoose.Promise = BPromise;
除exec(), execPopulate()系列函數(shù)外,mongoose多數(shù)API都是回調(diào)風(fēng)格的,通常需要用Bluebird將其Promisify。 這些Mongoose API主要包括下列三類(lèi):
Model. Eg: User.findAsync(), User.findByIdAsync(), User.removeAsync(), User.updateAsync()
Model.prototype. Eg: user.saveAsync(), user.removeAsync()
Query.prototype. Eg: User.find().sortAsync(), User.find().populateAsync()
BPromise.promisifyAll(mongoose.Model);
BPromise.promisifyAll(mongoose.Model.prototype);
BPromise.promisifyAll(mongoose.Query.prototype);
這些Promise化的代碼最好在代碼載入時(shí)執(zhí)行,但不要早于mongoose插件。否則這些插件就不會(huì)被Promise化了。
Promise化之后的mongoose用起來(lái)是這樣的:
var UserSchema = mongoose.Schema({
name: String,
phone: String
});
var User = mongoose.model('User', UserSchema);
User.findAsync()
.then(users => console.log(users));
.catch(e => console.error(e));
某些mongoose插件可能需要在Promisify腳本之后執(zhí)行較為方便。這時(shí)我們需要將受影響的模型再次Promise化:
var UserSchema = mongoose.Schema({...});
UserSchema.plugin(require('passport-local-mongoose'), {
usernameField: 'phone'
});
var User = mongoose.model('User', UserSchema);
BPromise.promisifyAll(User);
文章出處
總結(jié)
以上是生活随笔為你收集整理的html form callback,Promise异步编程模式总结初始化Promise对象统一错误处理PromisifyfromCallbackMongoose Promisify...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: w7怎么取消屏保 如何关闭W7屏保
- 下一篇: 中国石油计算机文化基础答案,中国石油大学