我想有条件地执行异步函数,但我想我错过了正确的语法来说出我想要的东西.
this.doUpToThreeThings = function(skipTheMiddleStep) {
return doFirstThing().then(function (result) {
if (skipTheMiddleStep) {
return doThirdThing();
} else {
return doSecondThing();
}
}).then(function (result) {
if (skipTheMiddleStep) {
return "ok"; // return what?
} else {
return doThirdThing();
}
});
}
Run Code Online (Sandbox Code Playgroud)
当我们到达第二个时,我不知道第一个块是否做了中间步骤,所以我不得不重复这个条件.第二个块看起来很奇怪:它应该说,如果跳过中间步骤,那么做第三件事,但既然我们知道前一个块必须完成第三件事,它就会返回.所以我必须重复这个条件,然后在第二个中编写看起来很错误的代码.
我意识到我可以编写一个名为doSecondAndThirdThings的函数,只是从第一个块中的条件调用它,但那不是真的DRY,它只是隐藏非DRYness.(或者我错了?)
另外,对于在"ok"分支上返回完成的承诺,我仍然有点困惑.它是正确的,或者我应该说像解决方案? - 谢谢
我还是Angular的新手并承诺所以我希望我在这里有正确的想法.
我目前有一个数据层服务,它使用restangular来获取一些数据,然后返回一个promise,就像这样......
dataStore.getUsers = function (params) {
return users.getList(params);
};
Run Code Online (Sandbox Code Playgroud)
然后,我调用此函数的控制器会收到一个承诺,就像这样......
$dataStore.getUsers(params).then(function (response) {
$scope.users = response;
}, function(response) {
$log.error("Get users returned an error: ", response);
});
Run Code Online (Sandbox Code Playgroud)
这很好用,但我想在传回数据存储之前使用我的数据存储区内的promise.我想使用.then()方法检查它是否失败并进行一些日志记录,然后,从sucess函数和失败函数我想将原始的promise返回给我的控制器.
然后,我的控制器可以像现在一样使用.then()方法,事实上,我不希望我的控制器代码完全改变,只是我的数据存储区代码.
这里有一些半伪代码来显示我想要的数据存储功能...
dataStore.getUsers = function (params) {
users.getList(params).then(function (response) {
$log("server responded")
return original promise;
}, function(response) {
$log.error("server did not respond");
return original promise;
});
};
Run Code Online (Sandbox Code Playgroud) 所以我有一个网站,点击一个按钮,它发送到一个角度服务,它提出一个承诺,解决它,获取一些数据,并在页面上显示该数据.我想要一个角度测试,找到按钮,点击它,并验证我得到了数据.但是,测试总是在按钮结算之前完成.我尝试了browser.sleep(),但这只是暂停了承诺从未解决的事情.关于量角器的许多其他与承诺相关的问题没有帮助,因为承诺没有在测试中设置,而是由页面本身设置.
这是我的测试:
it('should roll a d2', function () {
element(by.id('d2Button')).click();
//whatever has to be here for the waiting to occur
expect(element(by.binding('rolls.d2')).getText()).not.toEqual('0');
});
Run Code Online (Sandbox Code Playgroud)
这是HTML:
<button id="d2Button" type="button" class="btn btn-success" ng-click="rollD2()">Roll</button>
<span><b>{{rolls.d2 | number}}</b></span>
Run Code Online (Sandbox Code Playgroud)
以下是点击时调用的角度代码的简短摘要:
$scope.rollD2 = function () {
diceService.getD2Roll($scope.quantities.d2).then(function (data) {
$scope.rolls.d2 = data.roll;
});
};
Run Code Online (Sandbox Code Playgroud)
这是服务电话:
function getD2Roll(quantity) {
var url = "Dice/D2/" + quantity;
return getPromise(url);
}
function getPromise(url) {
var deferred = $q.defer();
$http.get(url).success(deferred.resolve).error(deferred.reject);
return deferred.promise;
}
Run Code Online (Sandbox Code Playgroud)
如何让测试正确等待?
我在页面上有多个使用相同服务的控制器,为了举例我们将调用服务USER.
第一次调用USER.getUser()时,它会对用户的GET数据执行$ http请求.调用完成后,它将数据存储在USER.data中.如果对USER.getUser()进行另一次调用,它会检查USER.data中是否有数据,如果有数据,则返回该数据,而不是进行调用.
我的问题是对USER.getUser()的调用发生得如此之快,以至于USER.data没有任何数据,因此它再次触发$ http调用.
以下是我现在为用户工厂提供的信息:
.factory("user", function($http, $q){
return {
getUser: function(){
var that = this;
var deferred = $q.defer();
if(that.data){
deferred.resolve(that.data);
} else {
$http.get("/my/url")
.success(function(res){
that.data = res;
deferred.resolve(that.data);
});
}
return deferred.promise;
}
}
});
Run Code Online (Sandbox Code Playgroud)
我希望我的问题有道理.任何帮助将非常感激.
我必须顺序执行三个不同的$ http-calls,它们相互依赖.到目前为止,我的工作解决方案是这样的
$http.get(".../1/...").success(function(){
$http.get(".../2/...").success(function(){
$http.get(".../3/...").success(function(){
});
});
});
Run Code Online (Sandbox Code Playgroud)
现在有一些变化:如果条件为真,则应跳过第一个调用.我可以这样做:
if(skipCallOne) {
$http.get(".../2/...").success(function(){
$http.get(".../3/...").success(function(){
});
});
} else {
$http.get(".../1/...").success(function(){
$http.get(".../2/...").success(function(){
$http.get(".../3/...").success(function(){
});
});
});
}
Run Code Online (Sandbox Code Playgroud)
这显然会导致大量的代码复制.我看到如果我使用特定$ http-calls的propper函数,这可以减少.但据我所知,更好的解决方案是正确使用和链接$ http-promises,如下所示:
$http.get(".../1/...").then(function(){
return $http.get(".../2/...");
}).then(function() {
return $http.get(".../3/...");
}).then(function() {
});
Run Code Online (Sandbox Code Playgroud)
但现在我的问题是,我如何以最少的代码复制条件跳过第一次调用?
在Angular中,以下片段似乎是等效的:
let deferred = $q.defer();
if(whatever) {
deferred.resolve('something');
}
else {
deferred.reject('nah');
}
return deferred.promise;
Run Code Online (Sandbox Code Playgroud)
和
return $q((resolve,reject) => {
if(whatever) {
resolve('something');
}
else {
reject('nah');
}
});
Run Code Online (Sandbox Code Playgroud)
我的问题:如果它们不相同,它们有何不同?如果它们是等价的,是否有令人信服的理由选择一个而不是另一个?
我最近参与了一个nodejs项目,当我尝试在我的数据库访问和我的路由之间使用promises时遇到错误在http:// localhost:8080 /上请求响应时发送它们后无法设置标题api /用户.虽然我知道堆栈上的许多解决方案都没有为我解决,所以这是我在router.js的路由代码
server.get('/api/user/', function (req, res) {
database.getUser()
.then(function(data){
res.send(data);
}, function(err){
res.send(500,{error: err});
});
});
Run Code Online (Sandbox Code Playgroud)
而database.js的第一部分包括函数getUser
(function() {
'use strict';
var Promise = require('bluebird'),
mysql = require("mysql"),
bcrypt = require('bcryptjs'),
client;
exports.connect = function(){
return new Promise(function(resolve, reject) {
client = mysql.createPool({
connectionLimit : 100,
waitForConnection: true,
host : 'localhost',
user : 'root',
password : 'root',
database : 'public',
debug : false
});
if(!client){
reject('Deu merda');
} …Run Code Online (Sandbox Code Playgroud) 下面是我的代码,我想要login()和authenticated()函数等待getProfile()函数完成它的执行.我尝试了几种方式,比如承诺等,但我无法实现它.请建议我的解决方案.
import { Injectable } from '@angular/core';
import { tokenNotExpired } from 'angular2-jwt';
import { myConfig } from './auth.config';
// Avoid name not found warnings
declare var Auth0Lock: any;
@Injectable()
export class Auth {
// Configure Auth0
lock = new Auth0Lock(myConfig.clientID, myConfig.domain, {
additionalSignUpFields: [{
name: "address", // required
placeholder: "enter your address", // required
icon: "https://example.com/address_icon.png", // optional
validator: function(value) { // optional
// only accept addresses with more than 10 chars
return …Run Code Online (Sandbox Code Playgroud) 我正在使用Angularjs 1.3.7,并且发现Promise.all在成功响应后不更新angularjs视图,而$ q.all确实如此.这是后来改变,因为Promises包含在原生javascript中或者背后的原因是什么?
浏览器控制台显示以下错误:
zone.js:668 Error: Uncaught (in promise): [object Undefined]
at resolvePromise (zone.js:814)
at resolvePromise (zone.js:771)
at zone.js:873
at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:188)
at drainMicroTaskQueue (zone.js:595)
at ZoneTask.push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask [as invoke] (zone.js:500)
at invokeTask (zone.js:1540)
at globalZoneAwareCallback (zone.js:1577)
Run Code Online (Sandbox Code Playgroud)
我不知道在哪里看源代码。
更新:在Firefox下打开的同一页面显示以下消息:
Error: Uncaught (in promise): [object Undefined]
Stack trace:
resolvePromise@http://localhost:4200/polyfills.js:3131:31
makeResolver/<@http://localhost:4200/polyfills.js:3041:17
setError@http://localhost:4200/scripts.js:979:21
messageCallback@http://localhost:4200/scripts.js:1092:25
./node_modules/zone.js/dist/zone.js/</ZoneDelegate.prototype.invokeTask@http://localhost:4200/polyfills.js:2738:17
./node_modules/zone.js/dist/zone.js/</Zone.prototype.runTask@http://localhost:4200/polyfills.js:2505:28
./node_modules/zone.js/dist/zone.js/</ZoneTask.invokeTask@http://localhost:4200/polyfills.js:2813:24
invokeTask@http://localhost:4200/polyfills.js:3857:9
globalZoneAwareCallback@http://localhost:4200/polyfills.js:3883:17
zone.js:668
Run Code Online (Sandbox Code Playgroud)
更新:如果该错误与我新添加的拦截器源代码有关,则这是我如何处理可能的异常:
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
return this.addAuthHeader(request, next);
}
private addAuthHeader(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
console.log('=======>> Intercepting the http …Run Code Online (Sandbox Code Playgroud) angular-promise ×10
angularjs ×8
javascript ×6
angular ×2
promise ×2
express ×1
mysql ×1
node.js ×1
protractor ×1
q ×1
rest ×1
restangular ×1