最近我开始在bluebird库中使用pg-promise。我一直在每个回调中嵌套回调和处理err
。我发现承诺中的catch
陈述看起来非常整洁。我不确定是否可以将此代码转为承诺基础?
username = username.toUpperCase();
let text = "SELECT * FROM users WHERE username = $1";
let values = [username];
database.one(text, values).then(function (userObject) {
// ANY WAY TO TURN this nested bycrypt into promise chain?
bcrypt.compare(password, userObject.password, function (err, same) {
if (err) {
return next(err, null);
}
if (!same) {
return next(new Error("Password mismatched!"), null);
}
const serializeObject = {_id: userObject._id};
return next(null, serializeObject);
});
}).catch(function (err) {
return next(err, null);
});
答案 0 :(得分:4)
我想使用bluebirds promisify,你会像这样宣传bcrypt.compare(你不必使用名称的Async部分)
public class MainActivity extends AppCompatActivity {
ListView listView;
Button sync;
ProgressDialog progressDialog;
String name, phone;
ArrayList<Contact_list> listitem;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listitem = new ArrayList<Contact_list>();
listView = (ListView) findViewById(R.id.listViewID);
registerForContextMenu(listView);
sync= (Button) findViewById(R.id.syncID);
sync.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// GET CONTACTS DATA
GetContactsIntoArrayList();
listView.setAdapter(new Custom_adapter(MainActivity.this, listitem));
Toast.makeText(MainActivity.this, "import", Toast.LENGTH_SHORT).show();
}
});
}
public void GetContactsIntoArrayList(){
Cursor cursor;
cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,null, null, null);
while (cursor.moveToNext()) {
name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
phone = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
listitem.add(new Contact_list(name,phone));
listView.setAdapter(new Custom_adapter(MainActivity.this, listitem));
}
cursor.close();
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> arg0, View v,
int index, long arg3) {
// TODO Auto-generated method stub
Log.v("long clicked","pos: " + index);
//Log.d("tag", "message");
String str=listView.getItemAtPosition(index).toString();
Log.d("long click sucessfull: " ,str);
return true;
}
});
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,ContextMenu.ContextMenuInfo menuInfo)
{
super.onCreateContextMenu(menu, v, menuInfo);
menu.setHeaderTitle("Select The Action");
menu.add(0, v.getId(), 0, "Call");
menu.add(0, v.getId(), 0, "Send SMS");
}
@Override
public boolean onContextItemSelected(MenuItem item)
{
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
// info.position will give the index of selected item
int IndexSelected=info.position;
if(item.getTitle()=="Call")
{
// Code to execute when clicked on This Item
}
else if(item.getTitle()=="Send SMS")
{
// Code to execute when clicked on This Item
//
}
else
{
return false;
}
return true;
}
}
因为第一个.then中的
let compareAsync = Promise.promisify(bcrypt.compare);
需要在第二个中使用。然后,你不能通过返回compareAsync简单地链接.then,因为那样下一个。然后不会。有权访问userObject
一个修正,是使用一个变量,它将在两个范围内。但是(但是)
userObject
另一个(在我看来更干净)选项是一个嵌套的.then
username = username.toUpperCase();
let text = "SELECT * FROM users WHERE username = $1";
let values = [username];
let uo; //hacky the outer scoped variable
database.one(text, values).then(function (userObject) {
uo = userObject;
return compareAsync(password, userObject.password);
}).then(function(same) {
if (!same) {
throw new Error("Password mismatched!");
}
const serializeObject = {_id: uo._id};
return next(null, serializeObject);
}).catch(function (err) {
return next(err, null);
});
注意:bluebird有一个promisifyAll函数...它在一个对象中传播函数,并在函数名称中添加(默认情况下)username = username.toUpperCase();
let text = "SELECT * FROM users WHERE username = $1";
let values = [username];
database.one(text, values).then(function (userObject) {
return compareAsync(password, userObject.password)
// [optional] following three lines to generate a "nicer" error for compare failure
.catch(function(err) {
throw "bcrypt.compare failed";
})
// nested .then to pass on the userObject and same at the same time
.then(function (same) {
return { same: same, userObject: userObject };
});
}).then(function (result) {
let same = result.same,
userObject = result.userObject;
if (!same) {
throw new Error("Password mismatched!");
}
let serializeObject = { _id: userObject._id };
return next(null, serializeObject);
}).catch(function (err) {
return next(err, null);
});
后缀 - 我相信你可以决定一个不同的后缀名,但是文档会告诉你更多
在宣传单一功能时,您自己声明名称 - 以上内容可以轻松实现
Async
然后您只需使用代码为let trumpIsBigly = Promise.promisify(bcrypt.compare);
trumpIsBigly
最后一种可能性
手工推出的promisified compareAsync(主要取决于vitaly-t&#39的答案,但附加内容)
compareAsync
现在,只有在没有错误的情况下,compareAsync将解析为传入值function compareAsync(password1, password2, inValue) {
return new Promise(function (resolve, reject) {
bcrypt.compare(password1, password2, function (err, same) {
err = err || (!same && new Error("Password mismatched!"));
if (err) {
reject(err);
} else {
resolve(inValue);
}
});
});
}
, AND 同样如此
inValue
这使得&#34;链&#34;很简单!
答案 1 :(得分:1)
这是为了扩展@ Jaromanda的答案,以防你只使用那一个功能,只想看看如何手动宣传它。
function samePassword(password1, password2) {
return new Promise(function (resolve, reject) {
bcrypt.compare(password1, password2, (err, same) => {
err = err || (!same && new Error("Password mismatched!"));
if (err) {
reject(err);
} else {
resolve();
}
});
});
}
db.one(text, values)
.then(userObject => {
return samePassword(password, userObject.password);
})
.catch(error => {
return next(error, null);
});
除此之外,promisify
方法是可行的方法。但要理解它有效地做了什么总是好的;)