Anuglar 6. Пост. Подписаться вставка записи дважды

0

Я пытаюсь объединить Angular 6 CRUD. Мой метод addCoins, кажется, добавляет запись дважды.

addCoin(name, price) {
const obj = {
  name: name,
  price: price
};

const uri = 'http://localhost/ng6crud/api/post-coins/' + name + '/' + price;

this
  .http
  .post(uri, obj)
  .subscribe(res =>
    console.log('Done'));
}

Я создал простой PHP api, который находится в каталоге ng6crud. Ниже приведен код для api/post-coins / - Если я использую postman для отправки в API, тогда он только вставляет данные один раз.

<?php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');
$path = ltrim($_SERVER['REQUEST_URI'], '/');    // Trim leading slash(es)
$elements = explode('/', $path);                // Split path on slashes

global $name, $price;

if(!empty($elements[3]))
{
  $name = $elements[3];
}

if(!empty($elements[4]))
{
  $price = $elements[4];
}

global $server;
$server = "localhost";
global $user;
$user = "someU";
global $pwd;
// $pwd = "someP"; // production
 $pwd = "someP"; // local
global $db;
$db = "someDb";

 //open connection to mysql db
$connection = mysqli_connect($server,$user,$pwd,$db) or die("Error " . mysqli_error($connection));

//fetch table rows from mysql db
$sql = "INSERT into coins (name, price) VALUES('" . $name . "','" . $price . "')";

// echo $sql;
// die();

if ($connection->query($sql) === TRUE) {
   // echo "Record updated successfully";
} else {
   // echo "Error updating record: " . $connection->error;
}

$connection->close();
?>

Комбинация файла.htaccess и тега "" в файле httpd-vhosts.conf позволяет api/post-coins/принимать два параметра для "name" и "price", которые должны быть включены в инструкцию sql insert - для пример api/post-coins/rupple/1.00 вставляет строку в db.

Ниже приведен файл.htaccess:

    IndexIgnore * # prevent directory listing

Order deny,allow
Allow from *

# ------------------------------------------
# Rewrite so that php extentions are not shown
RewriteEngine on

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule ^.*$ index.php%{REQUEST_URI} [QSA,L]

Ниже приведен тег Location в теге "" в файле httpd-vhosts.conf:

    <Location /post-coins>
        ForceType appllication/x-http-php
    </Location>

Еще раз, если я использую почтальона для отправки в api/post-coins/rupple/1.00, тогда только одна запись будет в db. При использовании услуги в пределах Углового 6 он дважды вставляет данные. Я попытался удалить.subscribe, но потом ничего не вставлено, и я попытался удалить два параметра в конце URL-адреса, но это результаты - две пустые записи.

заранее спасибо

Чтобы ответить на вопрос @Vikas относительно того, как я реализую, следующим является create.component.html:

<div class="panel panel-primary">
  <div class="panel-heading">
    {{ title }}
  </div>
  <div class="panel-body">
    <form [formGroup]="angForm" novalidate>
      <div class="form-group">
        <label class="col-md-4">Coin Name</label>
        <input type="text" class="form-control" formControlName="name" #name />
      </div>
      <div *ngIf="angForm.controls['name'].invalid && (angForm.controls['name'].dirty || angForm.controls['name'].touched)" class="alert alert-danger">
        <div *ngIf="angForm.controls['name'].errors.required">
          Name is required.
        </div>
      </div>
      <div class="form-group">
        <label class="col-md-4">Coin Price</label>
        <input type="text" class="form-control" formControlName="price" #price/>
      </div>
      <div *ngIf="angForm.controls['price'].invalid && (angForm.controls['price'].dirty || angForm.controls['price'].touched)" class="alert alert-danger">
        <div *ngIf="angForm.controls['price'].errors.required">
          Price is required.
        </div>
      </div>
      <div class="form-group">
        <button (click)="addCoin(name.value, price.value)" [disabled]="angForm.pristine || angForm.invalid" class="btn btn-primary">Add</button>
      </div>
    </form>
  </div>
</div>

Файл creat.component.ts:

    import { Component, OnInit } from '@angular/core';
import { CoinService } from '../../service/coin.service';
import { FormGroup,  FormBuilder,  Validators } from '@angular/forms';

@Component({
  selector: 'app-create',
  templateUrl: './create.component.html',
  styleUrls: ['./create.component.css']
})
export class CreateComponent implements OnInit {

  title = 'Add Coin';
  angForm: FormGroup;
  constructor(private coinservice: CoinService, private fb: FormBuilder) {
    this.createForm();
  }
  createForm() {
    this.angForm = this.fb.group({
      name: ['', Validators.required ],
      price: ['', Validators.required ]
    });
  }
  addCoin(name, price) {
    this.coinservice.addCoin(name, price);
  }
  ngOnInit() {
  }
}

И coin.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable()
export class CoinService {

  result: any;
  constructor(private http: HttpClient) {}

  addCoin(name, price) {
    const obj = {
      name: name,
      price: price
    };

    const uri = 'http://localhost/ng5crud/api/post-coins/' + name + '/' + price;

    this
      .http
      .post(uri, obj)
      .subscribe(res =>
        console.log('Done'));
  }

  getCoins() {
    const uri = 'http://localhost/ng5crud/api/get-coins/';
    return this
              .http
              .get(uri);
  }

  editCoin(id) {
    const uri = 'http://localhost/ng5crud/api/get-coins-id/' + id;
    return this
              .http
              .get(uri);
  }

  updateCoin(name, price, id) {
    const uri = 'http://localhost/ng5crud/api/put-coins/' + id;

    const obj = {
      name: name,
      price: price
    };
    this
      .http
      .post(uri, obj)
      .subscribe(res => console.log('Done'));
  }

  deleteCoin(id) {
    const uri = 'http://localhost/ng5crud/api/delete-coins/' + id;

    return this
              .http
              .get(uri);
  }
}

И routerConfig.ts

    import { Routes } from '@angular/router';
import { CreateComponent } from './components/create/create.component';
import { EditComponent } from './components/edit/edit.component';
import { IndexComponent } from './components/index/index.component';
import { DeleteComponent } from './components/delete/delete.component';

export const appRoutes: Routes = [
  { path: 'create',
    component: CreateComponent
  },
  {
    path: 'edit/:id',
    component: EditComponent
  },
  { path: 'index',
    component: IndexComponent
  },
  { path: 'delete/:id',
    component: DeleteComponent
  }
];

@Debojyoti, я только что видел ваш ответ. Я закончил создание следующего, которое ничего не вернуло, но я взглянул на сетевую панель - см. Снимок экрана ниже:

import { HttpErrorResponse } from '@angular/common/http';
import { throwError } from 'rxjs';
import { catchError} from 'rxjs/operators';

addCoin(name, price) {
  const obj = {
    name: name,
    price: price
  };

  const uri = 'http://localhost/ng5crud/api/post-coins/' + name + '/' + price;

  this
    .http
    .post(uri, obj)
    .pipe(
      catchError(this.handleError) // then handle the error
    )
    .subscribe(res =>
      console.log('Done'));
}

private handleError(error: HttpErrorResponse) {
  if (error.error instanceof ErrorEvent) {
    // A client-side or network error occurred. Handle it accordingly.
    console.error('An error occurred:', error.error.message);
  } else {
    // The backend returned an unsuccessful response code.
    // The response body may contain clues as to what went wrong,
    console.error(
      'Backend returned code ${error.status}, ' +
      'body was: ${error.error}');
  }
  // return an observable with a user-facing error message
  return throwError(
    'Something happened; please try again later.');
};

Изображение 174551

  • 0
    Вы подписываетесь дважды? поделиться кодом, где вы вызываете свой метод
  • 0
    @ Викас, я добавил код и, отвечая на твой вопрос, я не думаю, что подписываюсь на него дважды. По крайней мере, я не вижу его в моем коде, вызываемом дважды
Показать ещё 4 комментария
Теги:
angular

3 ответа

0

Я понял это, и я благодарю каждого из вас за то, что помог мне повторить это снова и снова.

Поскольку мой PHP API для всех интенсивных целей "GET":

const uri = 'http://localhost/ng5crud/api/post-coins/' + name + '/' + price;

Тогда вызов функции "POST" приведет к отключению API дважды - см. Прикрепленный снимок экрана ниже:

const obj = {
  name: name,
  price: price
};

const uri = 'http://localhost/ng5crud/api/post-coins/' + name + '/' + price;

this
  .http
  .post(uri, obj)

Таким образом, я изменил его на функцию "GET", и он работает отлично, только с одной записью

addCoin(name, price) {
    const obj = {
      name: name,
      price: price
    };

    const uri = 'http://localhost/ng5crud/api/post-coins/' + name + '/' + price;

    this
      .http
      .get(uri)
      .pipe(
        catchError(this.handleError), // then handle the error
        map(res => {
          console.log(res);
        })
      )
      .subscribe(res =>
        console.log('Done'));
  }

Изображение 174551

В этом путешествии я обнаружил (qaru.site/questions/15861178/...), что карта импортируется по-разному в Angular 6 и используется по-разному в методе.get

Вместо импорта с

    import 'rxjs/add/operator/map';

Вы используете следующее:

import { map } from 'rxjs/operators';

Вместо.get(). Map()

  this
  .http
  .get(uri)
  .map(res => {console.log(res)});

Вы используете карту, внутри.pipe

this
  .http
  .get(uri)
  .pipe(
    catchError(this.handleError), // then handle the error
    map(res => {
      console.log(res);
    })
  )

Все вместе, это моя новая рабочая монета.service.ts:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { HttpErrorResponse } from '@angular/common/http';
import { throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { map } from 'rxjs/operators';

@Injectable()
export class CoinService {

  constructor(private http: HttpClient) {}

  addCoin(name, price) {
    const obj = {
      name: name,
      price: price
    };

    const uri = 'http://localhost/ng5crud/api/post-coins/' + name + '/' + price;

    this
      .http
      .get(uri)
      .pipe(
        catchError(this.handleError), // then handle the error
        map(res => {
          console.log(res);
        })
      )
      .subscribe(res =>
        console.log('Done'));
  }

  getCoins() {
    const uri = 'http://localhost/ng5crud/api/get-coins/';
    return this
              .http
              .get(uri)
              .pipe(
                catchError(this.handleError), // then handle the error
                map(res => {
                  console.log(res);
                })
              );
  }

  editCoin(id) {
    const uri = 'http://localhost/ng5crud/api/get-coins-id/' + id;
    return this
              .http
              .get(uri)
              .pipe(
                catchError(this.handleError), // then handle the error
                map(res => {
                  console.log(res);
                })
              );
  }

  updateCoin(name, price, id) {
    const uri = 'http://localhost/ng5crud/api/put-coins/' + id;

    const obj = {
      name: name,
      price: price
    };
    this
      .http
      .post(uri, id)
      .pipe(
        catchError(this.handleError), // then handle the error
        map(res => {
          console.log(res);
        })
      )
      .subscribe(res => console.log('Done'));
  }

  deleteCoin(id) {
    const uri = 'http://localhost/ng5crud/api/delete-coins/' + id;

    return this
              .http
              .get(uri)
              .pipe(
                catchError(this.handleError), // then handle the error
                map(res => {
                  console.log(res);
                })
              );
  }

  private handleError(error: HttpErrorResponse) {
    if (error.error instanceof ErrorEvent) {
      // A client-side or network error occurred. Handle it accordingly.
      console.error('An error occurred:', error.error.message);
    } else {
      // The backend returned an unsuccessful response code.
      // The response body may contain clues as to what went wrong,
      console.error(
        'Backend returned code ${error.status}, ' +
        'body was: ${error.error}');
    }
    // return an observable with a user-facing error message
    return throwError(
      'Something happened; please try again later.');
  }
}

Серьезно, спасибо вам за вашу помощь. Это возвращает меня к началу девяностых, когда программисты были хороши, и мы помогали друг другу.

  • 0
    Здорово. Кроме того, да, метод импорта операторов RxJS изменился в 5.5, а пути импорта были упрощены в RxJS 6.x.
0

Сделать php не принимать первый запрос на предварительный рейс (ОПЦИИ)

Просто измените свой PHP-код, как

<?php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');

if ($_SERVER['REQUEST_METHOD'] != "OPTIONS") {
    $path = ltrim($_SERVER['REQUEST_URI'], '/'); // Trim leading slash(es)
    $elements = explode('/', $path); // Split path on slashes

    global $name, $price;

    if (!empty($elements[3])) {
        $name = $elements[3];
    }

    if (!empty($elements[4])) {
        $price = $elements[4];
    }

    global $server;
    $server = "localhost";
    global $user;
    $user = "someU";
    global $pwd;
    // $pwd = "someP"; // production
    $pwd = "someP"; // local
    global $db;
    $db = "someDb";

    //open connection to mysql db
    $connection = mysqli_connect($server, $user, $pwd, $db) or die("Error " . mysqli_error($connection));

    //fetch table rows from mysql db
    $sql = "INSERT into coins (name, price) VALUES('" . $name . "','" . $price . "')";

    // echo $sql;
    // die();

    if ($connection->query($sql) === TRUE) {
        // echo "Record updated successfully";
    } else {
        // echo "Error updating record: " . $connection->error;
    }

}

$connection->close();
?>
0

Похоже, что приложение PHP и приложение Angular работают на отдельной комбинации протокола (http/https), домена и порта. Я вижу, что заголовки CORS были добавлены в PHP-код.

Это заставляет меня думать, что сделано 2 запроса, чтобы проверить, разрешен ли запрос в соответствии с запросом CORS (OPTIONS) и обычным запросом POST. Следовательно, запись вставляется дважды. Вы можете обнаружить метод запроса и вернуть заголовки CORS и установить тело ответа как ничто в соответствии с запросом CORS OPTIONS и вставить запрос POST аналогичный следующему (не проверен).

<?php
if ($_SERVER['method'] === 'OPTIONS') {
    header('Access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS');
    header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');
    header("HTTP/1.1 200 OK");

    exit;
}

if ($_SERVER['method'] === 'POST') {
    header("HTTP/1.1 200 OK");

    $path = ltrim($_SERVER['REQUEST_URI'], '/');    // Trim leading slash(es)
    $elements = explode('/', $path);                // Split path on slashes

    global $name, $price;

    if (!empty($elements[3])) {
        $name = $elements[3];
    }

    if (!empty($elements[4])) {
        $price = $elements[4];
    }

    global $server;
    $server = "localhost";
    global $user;
    $user = "someU";
    global $pwd;
    // $pwd = "someP"; // production
    $pwd = "someP"; // local
    global $db;
    $db = "someDb";

    //open connection to mysql db
    $connection = mysqli_connect($server, $user, $pwd, $db) or die("Error " . mysqli_error($connection));

    //fetch table rows from mysql db
    $sql = "INSERT into coins (name, price) VALUES('" . $name . "','" . $price . "')";

    // echo $sql;
    // die();

    if ($connection->query($sql) === true) {
        // echo "Record updated successfully";
    } else {
        // echo "Error updating record: " . $connection->error;
    }

    $connection->close();

    exit;
}

header("HTTP/1.1 404 Not Found");
exit;

?>
  • 0
    Спасибо @ chris-mcknight, Все, что ты сказал, имело такой смысл, но все равно вставлялось дважды.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню